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 Expand
ing bar expands from left to right with all colors in it. A Flow
ing 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.