我快要在这里失去理智了。我在谷歌上搜索了一个小时,试图解决这个小问题,但问题却非常严重。
我的表单上有一个带有两个选项卡的 TabControl
。这些选项卡中的每一个都有一个 16x16 图标和一些文本。这里没有发生任何疯狂的事情。
我需要让其中一个选项卡图标在某些情况下闪烁。所以我创建了两个图像,和 并将它们添加到 TabControl
使用的 ImageList
中。我设置了一个背景计时器,在两个图像之间切换以模拟闪烁的图标。工作良好。
但是,它会导致所有选项卡标题重绘,从而使它们闪烁。
无论您尝试做什么,TabControl
都不支持双缓冲。
我发现人们使用这段代码成功地控制了闪烁:
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
Return cp
End Get
End Property
这是有效的,因为它不会闪烁...但图标也不再在视觉上发生变化,除非鼠标光标悬停在导致重绘的对象上。
有没有人有任何可能有效的替代解决方案或技巧?这实际上是该软件的一项非常重要的功能。
骨架代码:
Public Class Form1
Dim BlinkTimer As Windows.Forms.Timer
Dim BlinkToggler As Boolean = False
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
InitBlinker()
End Sub
Private Sub InitBlinker()
BlinkTimer = New Windows.Forms.Timer
AddHandler BlinkTimer.Tick, AddressOf Blinker_Tick
With BlinkTimer
.Enabled = True
.Interval = 250
End With
StartBlinker()
End Sub
Public Sub StartBlinker()
SomeTabPage.ImageKey = "light_off.png"
BlinkToggler = False
BlinkTimer.Start()
End Sub
Public Sub StopBlinker()
SomeTabPage.ImageKey = "light_off.png"
BlinkToggler = False
BlinkTimer.Stop()
End Sub
Private Sub Blinker_Tick()
If BlinkToggler Then
SomeTabPage.ImageKey = "light_on.png"
Else
SomeTabPage.ImageKey = "light_off.png"
End If
BlinkToggler = Not BlinkToggler
End Sub
End Class
最佳答案
这是手工绘制图像的快速技巧(有几处需要调整,但这只是一个开始)。
Imports System.Threading
Public Class MyTabControl
Inherits TabControl
Private tabsImages As New Concurrent.ConcurrentDictionary(Of TabPage, List(Of String))
Private tabsImagesKeys As New Concurrent.ConcurrentDictionary(Of TabPage, String)
Private cycleImagesThread As Thread
Private mInterval As Integer = 500
Public Sub New()
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.DrawMode = TabDrawMode.OwnerDrawFixed
cycleImagesThread = New Thread(AddressOf CycleImagesLoop)
cycleImagesThread.Start()
End Sub
Protected Overrides Sub OnHandleCreated(e As EventArgs)
If Me.FindForm IsNot Nothing Then AddHandler CType(Me.FindForm, Form).FormClosing, Sub() cycleImagesThread.Abort()
MyBase.OnHandleCreated(e)
End Sub
Private Sub CycleImagesLoop()
Do
Thread.Sleep(mInterval)
If tabsImagesKeys.Count > 0 Then
For Each tabImageKey In tabsImagesKeys
Dim index = tabsImages(tabImageKey.Key).IndexOf(tabImageKey.Value)
index += 1
index = index Mod tabsImages(tabImageKey.Key).Count
tabsImagesKeys(tabImageKey.Key) = tabsImages(tabImageKey.Key)(index)
Next
Me.Invalidate()
End If
Loop
End Sub
Public Property Interval As Integer
Get
Return mInterval
End Get
Set(value As Integer)
mInterval = value
End Set
End Property
Public Sub SetImages(tabPage As TabPage, images As List(Of String))
If tabsImages.ContainsKey(tabPage) Then
tabsImages(tabPage) = images
Else
tabsImages.TryAdd(tabPage, images)
End If
tabsImagesKeys(tabPage) = images.First()
End Sub
Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
Dim g As Graphics = e.Graphics
Dim r As Rectangle = e.Bounds
Dim tab As TabPage = Me.TabPages(e.Index)
Dim tabImage As Image
Using b = New SolidBrush(IIf(e.State = DrawItemState.Selected, Color.White, Color.FromKnownColor(KnownColor.Control)))
g.FillRectangle(b, r)
End Using
If tabsImagesKeys.Count > 0 OrElse Me.ImageList IsNot Nothing Then
If tabsImagesKeys.ContainsKey(tab) Then
tabImage = Me.ImageList.Images(tabsImagesKeys(tab))
g.DrawImageUnscaled(tabImage, r.X + 4, r.Y + (r.Height - tabImage.Height) / 2)
End If
r.X += Me.ImageList.ImageSize.Width + 4
End If
Using b = New SolidBrush(tab.ForeColor)
Dim textSize = g.MeasureString(tab.Text, tab.Font)
g.DrawString(tab.Text, tab.Font, b, r.X, r.Y + (r.Height - textSize.Height) / 2)
End Using
MyBase.OnDrawItem(e)
End Sub
End Class
按照以下步骤设置控件:
- 首先,将
ImageList
控件分配给MyTabControl
并用图像填充它。 接下来,调用
SetImages
方法来定义应该在每个选项卡上显示哪些图像。MyTabControl1.SetImages(TabPage1,新列表(字符串)来自 {“icon.gif”,“icon2.gif”}) MyTabControl1.SetImages(TabPage2,新列表(字符串)来自 {"myImage1.gif", "myImage2.gif"})
请注意,SetImages
方法的第二个参数是应该存在于 ImageList
上的键列表。
控件将完成剩下的工作......
关于c# - 更改选项卡图标时 TabControl 闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14287452/