Ano, System.Windows.Forms.Timer s voláním Start a Stop je bezproblémové řešení, při Dispose tlačítka případný běžící timer stopnu a zavolám na něm Dispose. Předpokládám rozdíl je v tom, že událost Timer_Tick běží ve stejném vlákně? Avšak vše funguje zcela bez problémů, ne, že bych timer dříve již nepoužil, dokonce je to i jednodušší. :) I tak bych rád věděl, jak lze ovládát a sledovat podprocesy v hlavním vlákně, beru to jako příležitost zkusit něco nového. Při hledání nějaké události, že vlákno se dokončilo, se mi povedlo zprovoznit AsyncCallback, přesto to vedlo k neočekávaným stavům při překreslování image tlačítka, tak jsem to nakonec úplně vzdal a předělal dle vaší rady. Mám dotaz ohledně Implements, pomohl by mi někdo v kostce naznačit, jak postupovat, abych mohl Blikání implementovat stejně do ToolStripButton, tak i do ToolStipLabel. Snažím se deklarovat Interface a snažím se protlačit property Blinking do buttonu i labelu, ale netuším, jak se dostat k objektu, v kterém jsme blikání implementoval. Kód pro ilustraci, kde pomocí jasu image tlačítka zkouším blikat či stmívat:
Imports System.Runtime.Remoting.Messaging
Public Class ToolStripBlinkingButton
Inherits ToolStripButton
Public Enum BlinkingButtonStyle
Blinker
Twilight
End Enum
Private _Image As Bitmap = Nothing
Delegate Function Delegate_FlashFinished() As Boolean
Private bRestart As Boolean
Sub Callback_FlashFinished(ByVal result As IAsyncResult)
Dim resultClass As AsyncResult = DirectCast(result, AsyncResult)
Dim d As Delegate_FlashFinished = DirectCast(resultClass.AsyncDelegate, Delegate_FlashFinished)
d.EndInvoke(result)
If bRestart Then StartBlinking()
End Sub
Private Sub StartBlinking()
_Image = Me.Image
If _Image Is Nothing Then _Blinking = False : Exit Sub
bRestart = False
_Blinking = True
Dim d As Delegate_FlashFinished = AddressOf FlashButton
d.BeginInvoke(New AsyncCallback(AddressOf Callback_FlashFinished), Nothing)
End Sub
Private _Blinking As Boolean
Public Property Blinking() As Boolean
Get
Blinking = _Blinking
End Get
Set(ByVal value As Boolean)
Dim bStart As Boolean
If Not _Blinking And value Then
bStart = True
End If
_Blinking = value
If bStart Then StartBlinking()
End Set
End Property
Private _BlinkingStyle As BlinkingButtonStyle = BlinkingButtonStyle.Blinker
Public Property BlinkingStyle() As BlinkingButtonStyle
Get
BlinkingStyle = _BlinkingStyle
End Get
Set(ByVal value As BlinkingButtonStyle)
If _Blinking And _BlinkingStyle <> value Then
bRestart = True
End If
_BlinkingStyle = value
If bRestart Then _Blinking = False
End Set
End Property
Delegate Sub SetImageCallBack(ByVal ico As Image)
Private Sub SetImage(ByVal img As Image)
Dim ts As ToolStrip = Me.GetCurrentParent
If ts Is Nothing Then
_Blinking = False
Else
If ts.InvokeRequired Then
Dim d As New SetImageCallBack(AddressOf SetImage)
ts.Invoke(d, New Object() {img})
Else
Me.Image = img
End If
End If
End Sub
Private Function FlashButton() As Boolean
Select Case _BlinkingStyle
Case BlinkingButtonStyle.Blinker
Dim bOrig As Boolean = True
Dim bmpShade As Bitmap = GetBrightness(_Image, 90)
While _Blinking
If Not bOrig Then
SetImage(_Image)
bOrig = True
Else
SetImage(bmpShade)
bOrig = False
End If
System.Threading.Thread.Sleep(750)
End While
Case BlinkingButtonStyle.Twilight
Dim iPercent As Integer = 100
Dim iPlusMinus As Integer = -1
While _Blinking
iPercent = iPercent + iPlusMinus * 5
If iPlusMinus < 0 And iPercent < 80 Then
iPlusMinus = 1
End If
If iPlusMinus > 0 And iPercent = 100 Then
iPlusMinus = -1
End If
Dim bmp As Bitmap = GetBrightness(_Image, iPercent)
SetImage(bmp)
System.Threading.Thread.Sleep(200)
End While
End Select
SetImage(_Image)
Return True
End Function
End Class
|