Imports System.Drawing.Drawing2D
Imports System.Timers
Public Class FlashLabel
Inherits Control
Private _clock As New Clock(200, 1)
Private _effectForeColor As Color = Color.Transparent
Private _showBorder As Boolean = True
Public Sub New()
MyBase.DoubleBuffered = True
End Sub
Public Property ShowBorder As Boolean
Get
Return Me._showBorder
End Get
Set(value As Boolean)
Me._showBorder = value
Me.Refresh()
End Set
End Property
Public Property EffectForeColor As Color
Get
Return Me._effectForeColor
End Get
Set(value As Color)
Me._effectForeColor = value
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
If MyBase.Width > 0 AndAlso MyBase.Height > 0 Then
If Me._showBorder Then
Dim bmp As Bitmap = New Bitmap(MyBase.Width, MyBase.Height)
Using gr As Graphics = Graphics.FromImage(bmp)
Dim rect As Rectangle = New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim gb As New LinearGradientBrush(rect, Color.FromArgb(88, MyBase.BackColor), Color.FromArgb(44, MyBase.BackColor), LinearGradientMode.Vertical)
gr.FillRectangle(gb, rect)
Dim borderColor As Color = If((CDec(MyBase.BackColor.GetBrightness()) < 0.5), ControlPaint.Light(MyBase.BackColor), ControlPaint.Dark(MyBase.BackColor))
gr.DrawRectangle(New Pen(borderColor), New Rectangle(0, 0, bmp.Width - 1, bmp.Height - 1))
End Using
e.Graphics.DrawImage(bmp, 0, 0)
If bmp IsNot Nothing Then
bmp.Dispose()
bmp = Nothing
End If
End If
If Not MyBase.Text Is Nothing Then
Dim g As Graphics = e.Graphics
Dim txtSize As SizeF = g.MeasureString(MyBase.Text, MyBase.Font)
Dim y As Integer = (MyBase.Height - CInt(txtSize.Height)) / 2
Dim x As Integer = (MyBase.Width - CInt(txtSize.Width)) / 2
Dim sb As New SolidBrush(MyBase.ForeColor)
g.DrawString(MyBase.Text, MyBase.Font, sb, x, y)
End If
End If
End Sub
Private Sub DisposeEffect()
If _clock IsNot Nothing Then
_clock.Dispose()
_clock = Nothing
End If
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
DisposeEffect()
End If
End Sub
Protected Overrides Sub OnMouseEnter(e As EventArgs)
MyBase.OnMouseEnter(e)
_clock.Allocate(Me, Me.ForeColor, Me.EffectForeColor)
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
_clock.Release(Me)
End Sub
Private Class Clock
Implements IDisposable
Protected _effects As List(Of ForeColorAnimation)
Protected _clock As Timer
Protected _speed As Integer
Protected _interval As Double = 40
Protected _allowEffect As Boolean
Public Sub New()
Me.New(1)
End Sub
Public Sub New(capacity As Integer)
Me.New(200, capacity)
End Sub
''' <summary>
''' create new clock class
''' </summary>
''' <param name="speed">animation speed</param>
''' <param name="capacity">number of controls to Animate</param>
Public Sub New(speed As Double, capacity As Integer)
_clock = New Timer()
_clock.Interval = speed
_speed = 1
AddHandler _clock.Elapsed, AddressOf Tick
_effects = New List(Of ForeColorAnimation)(capacity)
End Sub
Private Sub Start()
_clock.Start()
End Sub
Private Sub [Stop]()
_clock.Stop()
End Sub
Private Sub Tick(sender As Object, e As ElapsedEventArgs)
ProcessEffect()
End Sub
Private Sub ProcessEffect()
_allowEffect = Not _allowEffect
If _allowEffect Then
For Each e As ForeColorAnimation In _effects
e.Control.ForeColor = e.EffectColor
Next
Else
For Each e As ForeColorAnimation In _effects
e.Control.ForeColor = e.ForeColor
Next
End If
End Sub
Public Sub Dispose()
If _clock IsNot Nothing Then
_clock.Dispose()
_clock = Nothing
End If
End Sub
Private Sub IDisposable_Dispose() Implements IDisposable.Dispose
Me.Dispose()
End Sub
Public Sub Allocate(ctrl As Control, oldForeColor As Color, newForeColor As Color)
For Each e As ForeColorAnimation In _effects
If e.Control Is ctrl Then
Return
End If
Next
_effects.Add(New ForeColorAnimation() With {.Control = ctrl, .ForeColor = oldForeColor, .EffectColor = newForeColor})
_allowEffect = True
Start()
ctrl.ForeColor = newForeColor
End Sub
Public Sub Release(ctrl As Control)
For Each e As ForeColorAnimation In _effects
If e.Control Is ctrl Then
ctrl.ForeColor = e.ForeColor
_effects.Remove(e)
If _effects.Count = 0 Then
[Stop]()
End If
Exit For
End If
Next
End Sub
End Class
Private Structure ForeColorAnimation
Public Control As Control
Public ForeColor As Color
Public EffectColor As Color
End Structure
End Class