Introduction
After initially searching for the animation used in SQL Server 2005 as an AVI or GIF, I stumbled across the excellent article by Amr Aly Elsehemy, here at The Code Project. Although good code, and indeed a starting point for what I have created, it didn't actually replicate the look and feel of the Microsoft SQL Server 2005 'busy' animation.
At less than 220 lines, I think that this control is pretty compact, and it seems to perform well, even when other threads in my application are busy.
Code
I store each 'segment' of the progress bar in an array, this makes it easy to iterate through later.
Private segmentPaths(11) As Drawing2D.GraphicsPath
The segments are initialized in the CalculateSegments
method, which is called when the control is initialized or resized. This method also generates a region which is used to clip the center circle back out when painting the control.
For intCount As Integer = 0 To 11
secmentPaths(intCount) = New Drawing2D.GraphicsPath
secmentPaths(intCount).AddPie(rctFull, (intCount * 30) - 90, 25)
Next
The ProgressDisk_Paint
method is where all the real work goes on (with the exception of the automatic iteration). I think the code speaks for itself, especially the comments :-)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
e.Graphics.ExcludeClip(innerBackgroundRegion)
For intCount As Integer = 0 To 11
If Me.Enabled Then
If intCount = m_TransitionSegment Then
e.Graphics.FillPath(New SolidBrush(m_TransistionColour), _
segmentPaths(intCount))
ElseIf intCount < m_TransitionSegment Then
If m_BehindIsActive Then
e.Graphics.FillPath(New SolidBrush(m_ActiveColour),_
segmentPaths(intCount))
Else
e.Graphics.FillPath(New SolidBrush(m_InactiveColour), _
segmentPaths(intCount))
End If
Else
If m_BehindIsActive Then
e.Graphics.FillPath(New SolidBrush(m_InactiveColour),_
segmentPaths(intCount))
Else
e.Graphics.FillPath(New SolidBrush(m_ActiveColour),_
segmentPaths(intCount))
End If
End If
Else
e.Graphics.FillPath(New SolidBrush(m_InactiveColour), _
segmentPaths(intCount))
End If
Next
The only other real work is done by the timer increment, which is fired by default every 100ms, but this is exposed as a property.
If m_TransitionSegment = 11 Then
m_TransitionSegment = 0
m_BehindIsActive = Not m_BehindIsActive
ElseIf m_TransitionSegment = -1 Then
m_TransitionSegment = 0
Else
m_TransitionSegment += 1
End If
Invalidate()
The m_BehindIsActive
variable decided whether all the segments behind (anti-clockwise) the transision segment (the segment currently changing colour) should be coloured using the active or inactive colour, both of which are user definable.