
Introduction
ColorBar is a gradient colored progress bar control, written in VB.NET. It was created to add interest to the progress bars in my application.
Using the Code
In your project, add a reference to ColorBar.dll. You may also add the control to the VS toolbox, so you can drag n' drop it on to your form or instantiate it from within your code (this is what the sample application does).
The control is used similar to a regular progress bar control. Set the Minimum and Maximum properties accordingly; then increment the Value property. The Smoothness property controls the coarseness of the gradient from one color to the next.
The BarStyle property can be set to Expand, Flow, or Block. An Expanding bar expands from left to right with all colors in it. A Flowing bar flows from left to right, exposing each color as it goes and, finally, a Block style bar is a flowing bar with 'outset' blocks. The Block style bar (not available in circular orientation) is affected by the width of the control, the number of colors in the color list, and the smoothness of the gradient.
A ColorBar with Minimum Smoothness:

A Block Style ColorBar:

The rainbow colors, ROYGBIV, plus Cyan, are the default colors used in the control. If you wish to use your own colors, simply make a list with a minimum of two colors and assign this list to the ColorList property. To revert to the default list, assign the ColorList property a value of Nothing. A long lists of colors will start to push together and may not look "smooth" in controls of short lengths.
A ColorBar with Custom Colors:

A Vertical ColorBar with Default Colors:

A Circular ColorBar with Default Colors and Thickness:

A Circular ColorBar with Custom Colors and Thicknesses:

Creating the ColorBar control (from code) is simple and straight-forward:
Dim cb as ColorBar
cb = New ColorBar
cb.Size = New Size(300, 18)
cb.Location = New Point((Me.ClientRectangle.Width / 2) - (cb.Size.Width / 2), 50)
cb.Visible = True
cb.Parent = Me
Me.Controls.Add(cb)
cb.Smoothness = ColorBar.MaxSmoothness
cb.Style = ColorBar.BarStyle.Expand
Adding custom colors is also easy:
Dim lstColors As New List(Of Color)
lstColors.Add(Color.Red)
lstColors.Add(Color.Green)
cb.ColorList = lstColors
To remove custom colors:
cb.ColorList = Nothing
Points of Interest
This control is double-buffered to avoid flicker:
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or _
ControlStyles.DoubleBuffer Or ControlStyles.Opaque, True)
Me.UpdateStyles()
The WM_ERASEBKGND message is also ignored in an attempt to avoid flicker:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = &H14 Then Return
End If
MyBase.WndProc(m)
End Sub
The interpolated color list is created with the following routines. For every two colors, an interpolated color is found and inserted back in the list.
Private Function InterpolateColors(ByVal color1 As Color, ByVal color2 As Color) As Color
Return Color.FromArgb(CInt((CInt(color1.R) + CInt(color2.R)) / 2), _
CInt((CInt(color1.G) + CInt(color2.G)) / 2), _
CInt((CInt(color1.B) + CInt(color2.B)) / 2))
End Function
Private Sub BuildColorList(ByRef lstAdd As List(Of Color))
lstColors = New List(Of Color)
Dim c As Color
For Each c In lstAdd
lstColors.Add(c)
Next
Dim idx As Integer Dim cnt As Integer Dim sdc As Integer
For sdc = 0 To m_Smoothness Step 1
idx = 0
cnt = lstColors.Count - 1
While idx < cnt
lstColors.Insert(idx + 1, InterpolateColors(lstColors(idx), _
lstColors(idx + 1)))
idx += 2
cnt += 1
End While
Next sdc
End Sub
Painting the progress bar is done in the OnPaint event. It divides the "completed" rectangle into equal portions for each color.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
Dim percentComplete As Single = CSng((m_Value - m_Minimum) / _
(m_Maximum - m_Minimum))
If percentComplete <= 0.0F Then Exit Sub
If percentComplete > 1.0F Then percentComplete = 1.0F
Dim fullWidth As Single = CSng(Me.ClientRectangle.Width - BorderWidth)
Dim totalWidth As Single = fullWidth * percentComplete
Dim barWidth As Single
If m_Style = BarStyle.Expand Then
barWidth = totalWidth
Else
If m_Style = BarStyle.Flow Or m_Style = BarStyle.Block Then
barWidth = fullWidth
End If
End If
barWidth /= CSng(lstColors.Count)
Dim height As Single = CSng(Me.ClientRectangle.Height - BorderWidth)
Dim halfBorder As Single = CSng(BorderWidth / 2)
Dim x As Single = halfBorder
Dim idxColor As Integer = 0
For x = halfBorder To totalWidth Step barWidth
e.Graphics.FillRectangle(New SolidBrush(lstColors(idxColor)), x, _
halfBorder, barWidth, height)
If barWidth > 4 And Me.Style = BarStyle.Block Then
ControlPaint.DrawBorder(e.Graphics, New Rectangle(CInt(x), _
CInt(halfBorder), CInt(barWidth), CInt(height)), _
Color.Gray, ButtonBorderStyle.Outset)
End If
If idxColor < lstColors.Count Then
idxColor += 1
End If
Next
If (x < (Me.ClientRectangle.Width - halfBorder)) And percentComplete = 1.0 Then
If idxColor < lstColors.Count Then
e.Graphics.FillRectangle(New SolidBrush(lstColors(idxColor)), x, halfBorder, _
((Me.ClientRectangle.Width - halfBorder) - x), height)
End If
End If
MyBase.OnPaint(e)
End Sub
Enjoy!
Suggestions
The ColorBar can be modified to be drawn (or behave) just about any way one desires by defining your own OnPaint method and/or modifying the properties. Perhaps, inherit from the Windows.Forms base class control instead of UserControl and then draw your own border using the ControlPaint class. There are many possibilities.
Random Thoughts/Improvements
- Recode using C# (to allow for property names that aren't keywords).
- Add a
Step property and PerformStep/Increment methods (some may find these handy).
- The control properties can be set from the Windows Forms Designer, but the list of colors is not retained when entered by hand.
- Grayscale option.
- Use GDI or GDI+ gradients as opposed to the do-it-yourself kind. (The do-it-yourself method is more fun :).)
- Marquee style control.
- Display percentage complete or current value.
- Thread safety.
History
- Initial creation - 04/26/2008.
- Corrected spelling/formatting - 05/03/08.
- Added brush buffering and other minor improvements - 05/24/08.
- Removed
Finalize method - 05/24/08.
- Added vertical and circular orientations; reversible color list; variable thicknesses for circular type; other minor code improvements - 06/14/08.