2013-01-11 21 views
6

ここで私の心を失うことについて。私はこのマイナーな問題を解決しようと1時間はグーグルグーグルしてきましたが、信じられないほど悪化している問題です。タブのアイコンを変更するとTabControlが点滅する

私はTabControlのフォームに2つのタブがあります。これらの各タブには、16×16のアイコンとテキストがあります。何もここで狂っていることはありません。

特定の状況でタブアイコンの1つを点滅させる必要があります。そこで、light_on.pnglight_off.pngという2つの画像を作成し、TabControlで使用されているImageListに追加しました。私は点滅しているアイコンをシミュレートするために2つのイメージを切り替えるバックグラウンドタイマーを設定しました。正常に動作します。

ただし、すべてのタブヘッダーが再描画されているため、ちらつきが発生しています。

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 
+0

...私はここから離れているかもしれませんが、アニメーションGIFはどうですか?それでは心配する必要はありませんか? –

+0

TabControlをダブルバッファーにすることはできませんので、おそらくこの制限を守らなければなりません。または、あなたの点滅する電球が画面上のどこかで点滅するように設計する必要があります。 – LarsTech

+0

@JohnBus​​tos私はアニメーションGIFを試しました、動作しません(アニメーション化しません)。それは私が探していた提案の一つです。ありがとう。 – user1003916

答えて

3

これは手で画像の描画を行うには(そこに微調整を必要とするいくつかのことがありますが、それはスタートだ)迅速なハックです。 MyTabControlImageListコントロールを割り当て、画像とそれを埋める、すべての

  1. まず:
    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 
    

    はセットアップに制御を次の手順に従います。
  2. 次に、どの画像を各タブに表示するかを定義するには、SetImagesメソッドを呼び出します。 { "myImage1.gifから MyTabControl1.SetImages(TabPage2、()文字列の新たなリスト({ "icon.gif"、 "icon2.gif"}からTabPage1、文字列の新しいリスト())

    MyTabControl1.SetImages 」、 『myImage2.gif』})

SetImages方法の第2のパラメータはImageListに存在することになっているキーのリストであること。 コントロールは残りの部分を行います...

+0

素晴らしい投稿、ありがとうございます。 – user1003916

関連する問題