Click here to Skip to main content
13,358,079 members (57,551 online)
Click here to Skip to main content
Add your own
alternative version


170 bookmarked
Posted 18 May 2005


, 26 May 2005
Rate this:
Please Sign up or sign in to vote.
The only progress bar you will ever need
Sample Image - BusyBar_2.png


There are a lot of articles about progress bars (about a dozen in CodeProject [^] ) and they all have different properties. My aim in writing BusyBar was to make all the different styles available in one control. I have coded about twenty-five styles, but the real beauty of BusyBar is that it is easily extendable. I hope that people will give me new styles as they write them, to include in this project.

Using the Code

First, you must add BusyBar to your project. I have packaged BusyBar as a single C# source file (BusyBar.cs) and its associated RESX file (BusyBar.resx). Visual Studio is a bit temperamental, so please follow these instructions in order:

  • Copy the two files to your project directory.
  • Add a reference to System.Design.dll to your project.
  • Add BusyBar.cs to your project; BusyBar.resx will be added automatically.
  • Open BusyBar.cs in the designer; I have no idea why this is necessary.
  • Compile your project.
  • Add your assembly to your toolbox.

Here are detailed instructions for the "Add your assembly to your toolbox" step (it's not that obvious):

  • Display your toolbox.
  • Select the "My User Controls" tab on your toolbox.
  • Right-click and select "Add/Remove Items..."
  • The "Customize Toolbox" dialog appears.
  • Click "Browse..."
  • Browse to the (project)/bin/Release folder and select your *.exe.
  • Click "OK."

I have also now packaged it in a control library, as requested for VB.NET developers. You should now have the BusyBar control and some Painter components in your toolbox. Note that, they will only be enabled when you have a form open in design view. You are now ready to add a BusyBar control to your form. First, a quick diagram to help you to understand how BusyBar works:

The BusyBar class is a custom control, and handles the control stuff, like the CornerRadius, and the data properties, like the minimum, maximum and current values. It is also responsible for drawing the border, but it delegates the rest of the painting to an instance of IPainter. I have written some implementations of IPainter, each of which has various Preset settings.

You are now ready to add an instance of BusyBar to your form. This will draw the border, but you need to select an IPainter to draw the client area. You can do this in one of three ways:

  1. Add an instance of one of the Painters to your form ( they all derive from Component ), and set the PainterObject property of your BusyBar to point to your Painter. This is probably the easiest way. You can then set the properties of your Painter from within the form designer. Note that all the Painters have a Preset property. This is not persisted, but setting it will set the properties of your BusyBar and Painter to some predefined values.
  2. Set the value of the PainterPreset property of your BusyBar to one of the enumeration values. At runtime, the BusyBar will create an instance of the corresponding Painter. You can access this object through the PainterWorker property of your BusyBar, and set its properties in the code behind your form.
  3. Do it all in code. You can set either the PainterObject or PainterPreset properties of your BusyBar in code, and then set the Painter's properties through the PainterWorker property as above. This is the way to use a custom Painter if you write your own.

And that's it. :) You can use the demo to test various settings, and to see the different styles available so far.

Adding Design-time Bitmaps

You will notice that the BusyBar control and the Painter components have default bitmaps in your toolbox. If you want pretty bitmaps, you have to follow a few more steps:

  • Add the bitmaps to your project. Create a new folder called "Bitmaps" in your project and copy the bitmap files into it.
  • Set the Build action. Select the bitmap files in Solution Explorer and change the "Build Action" property to "Embedded Resource."
  • Set your default namespace. There is a class called ResFinder defined at the top of the BusyBar.cs file. Change the value of the DefaultNamespace constant to your default namespace. See "Points Of Interest" for an explanation.
  • Build your project. You may have to Rebuild your Solution.
  • Delete the old Toolbox items from your toolbox.
  • Add your assembly to your toolbox again.

You should now have shiny new bitmaps showing in your Toolbox :)

The Painters

This section will help you to choose a Painter, and explain the properties specific to each. I haven't included images of the different presets as there are too many. You can run the demo to see examples of what is possible.


This was the first painter I wrote, just to test the BusyBar control. So it's quite simple, but may be of some use. It only has one preset, "Bar," which sets the width of the line to 50, so it appears as a block of colour.


This is an attempt to replicate the .NET ProgressBar control. This Painter introduces the concept of "Blocks." When the BlockLineWidth property is greater than 0, a series of lines are drawn over the bar. When the BlockLineColor property is set to the BackgroundColor of the control, this splits the bar up into blocks.

It has two presets: "System," which sets the Bar.Pin property to BusyBar.Pins.Start, which anchors the bar on the left or top sides; and "Startup," which is a copy of the bar XP shows at startup.


This is one of the most useful and configurable Painters. It uses a PathGradientBrush to paint the bar, which means you can set the colour gradient in two dimensions. Set the Shape property to one of the enumeration values to specify the base shape, and then set the Color properties to define the brush.

It has five presets: "Kitt," "Circle," "Startup," "Startup2003" and "Noise." These show the large range of effects that this Painter can produce. You get points if you know where the "Kitt" preset comes from :)


This Painter works best for a larger, square or slightly rectangular BusyBar control. It draws 12 marks round the edges, and two "hands" that rotate. It has two presets: "Watch" and "Circle." Note that the "Watch" preset is in CP colours!


This Painter is supposed to imitate an oscilloscope. The line is drawn as a GraphicsPath. This is defined by the Shape and Points properties. If the Shape property is set to Line, then path.AddLines( points ) is called to create the path. This just results in straight lines connecting the points.

If the Shape property is set to Curve, then path.AddCurve( points, 1, points.Length - 3, tension / 100f ) is called to create the path. This results in curves connecting the middle points. The two end points are not drawn, they are just there to define the curvature at the start and end of the path. So this Shape requires at least four points.

If the Shape property is set to Bezier, then path.AddBeziers( points ) is called to create the path. This results in curves connecting the points. This Shape requires one point for the start position, and then three more points to describe each segment. So it must have 4, 7, 10, ... (1 + 3n) ... points.

Note that the "size" of the path described by the points array does not matter. The path is scaled according to the HorizontalScale and VerticalScale properties, which are percentages of the BusyBar control client area. Also, if the control is in Vertical mode, the path is rotated 90 degrees clockwise, so the points array must always be set horizontally.

There are a few presets in this Painter. "Triangle", "Square" and "Saw" are based on the Line shape; "Sine" is based on the Curve shape; and "Bezier" is based on the Bezier shape. The other two presets, "Circle" and "Heartbeat" are just for fun :)


This Painter is a copy of the progress bar shown during an OS installation. I wrote it from memory; I think it's about right. It has two presets: "Install," which is the classic install bar, and "LED," which imitates a row of (blue) LEDs.


This is a joke (I hope). It displays a bar that looks like the one in IE. It displays the log of the value, so it seems to go fast at first, and then slows down. Then it resets itself when it reaches a specified percentage, so it never gets to 100%. This was requested (honest)!

Writing Your Own Painter

All Painters must implement the IPainter interface :

public interface IPainter : ICloneable
    IPainter CreateCopy();
    BusyBar BusyBar { get; set; }
    void Reset();
    void Paint( Graphics g, Region r );

You probably want to inherit from one of the existing classes. The derivation structure looks like this :


If you derive from PainterBase, you just have to override the CreateCopy and Paint methods. PainterBase holds a reference to the BusyBar control, which it makes available through the protected Bar property. It also handles the ICloneable interface.

The Paint method is the most interesting. It is called from the OnPaint method of the BusyBar control, after it has drawn the border. The Graphics parameter enables you to do your drawing, and the Region parameter defines the client area available to you. The clip region of the Graphics object is already set to this Region.

The best way to understand this design is to have a look at the existing concrete Painter implementations.

Note: To test your Painter in the demo, alter the Painter property of Form1 to return an instance of your Painter (it's at the end of Form1.cs ). You will then be able to play with the settings from the PropertyGrids.

Have fun :)

Points of Interest

Getting the design-time bitmaps to work was a real pain. When Visual Studio embeds a resource, it pretends the default namespace to the name, and this is not configurable ( someone thought this was a good idea! ). Because BusyBar.cs is designed to be included in any project, the default namespace cannot be known. So I added a class called ResFinder in the default namespace, but you have to set the DefaultNamespace constant manually. I could not find a way around this :(

Bob Powell's website was a great help, in particular his article "How to find the elusive ToolboxBitmap icon" [^].


BusyBar provides a lot of functionality out of the box, but I hope that people will write more extensions, and email them to me to be included in updates of this article. Appropriate credit will of course be given.

I have had fun writing this, especially the "Kitt" and "Heartbeat" presets were quite gratifying. I hope you like what I have done :)


  • 19th May 2005 : Version 1
  • 26th May 2005 : Version 2
    • Fixed the threading bug in the demo.
    • Removed SCC links as requested.
    • Packaged in a strong-named library assembly as requested.
    • Added preset "Startup" to PainterXP.
    • Added preset "Startup2003" to PainterPathGradient.
    • Added PainterInstall with two presets.
  • 27th May 2005 : Version 3
    • Fixed bug when Minimum was not zero.
    • Added PainterFrustratoBar as requested.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Nicholas Butler
United Kingdom United Kingdom

I built my first computer, a Sinclair ZX80, on my 11th birthday in 1980.
In 1992, I completed my Computer Science degree and built my first PC.
I discovered C# and .NET 1.0 Beta 1 in late 2000 and loved them immediately.
I have been writing concurrent software professionally, using multi-processor machines, since 1995.

In real life, I have spent 3 years travelling abroad,
I have held a UK Private Pilots Licence for 20 years,
and I am a PADI Divemaster.

I now live near idyllic Bournemouth in England.

If you would like help with multithreading, please contact me via my website:

I can work 'virtually' anywhere!

You may also be interested in...

Comments and Discussions

GeneralSystem.NullReferenceException occurred Pin
dchris_med10-May-07 21:48
memberdchris_med10-May-07 21:48 
Generalshape Pin
NRG568-Apr-07 8:43
memberNRG568-Apr-07 8:43 
GeneralStatusStrip Pin
rykema21-Feb-07 7:19
memberrykema21-Feb-07 7:19 
GeneralRe: StatusStrip Pin
rykema21-Feb-07 11:17
memberrykema21-Feb-07 11:17 
I found some useful links that have pointed me in the right direction...maybe they'll help someone else as well.

How to write a loading circle animation in .NET?


How to: Wrap a Windows Forms Control with ToolStripControlHost
GeneralBrilliant Pin
ChewsHumans6-Feb-07 16:06
memberChewsHumans6-Feb-07 16:06 
QuestionLicense? Pin
enovales9-Dec-05 9:05
memberenovales9-Dec-05 9:05 
GeneralI can't use BusyBar Pin
Afsoon30-Aug-05 4:03
memberAfsoon30-Aug-05 4:03 
QuestionHow do you change properties programmatically? Pin
BruceN31-May-05 13:56
memberBruceN31-May-05 13:56 
AnswerRe: How do you change properties programmatically? Pin
Nicholas Butler31-May-05 14:37
memberNicholas Butler31-May-05 14:37 
GeneralRe: How do you change properties programmatically? Pin
BruceN31-May-05 15:05
memberBruceN31-May-05 15:05 
General.NET CF Pin
otherJohn31-May-05 6:08
sussotherJohn31-May-05 6:08 
GeneralRe: .NET CF Pin
Nicholas Butler31-May-05 14:38
memberNicholas Butler31-May-05 14:38 
GeneralVersion 3 now available Pin
Nicholas Butler26-May-05 23:07
memberNicholas Butler26-May-05 23:07 
QuestionIs there automatic support for the Frustrato-Bar? Pin
Anonymous26-May-05 14:55
sussAnonymous26-May-05 14:55 
AnswerRe: Is there automatic support for the Frustrato-Bar? Pin
Nicholas Butler26-May-05 23:05
memberNicholas Butler26-May-05 23:05 
GeneralVersion 2 now available Pin
Nicholas Butler26-May-05 0:24
memberNicholas Butler26-May-05 0:24 
GeneralGreat Pin
Douglas Troy24-May-05 8:06
memberDouglas Troy24-May-05 8:06 
GeneralRe: Great Pin
Nicholas Butler26-May-05 0:22
memberNicholas Butler26-May-05 0:22 
GeneralCool Project -- one comment Pin
Paul Brower23-May-05 4:06
memberPaul Brower23-May-05 4:06 
GeneralRe: Cool Project -- one comment Pin
Nicholas Butler26-May-05 0:21
memberNicholas Butler26-May-05 0:21 
GeneralLooks Cool... Pin
jonnyvee21-May-05 12:11
memberjonnyvee21-May-05 12:11 
GeneralRe: Looks Cool... Pin
Nicholas Butler21-May-05 17:50
memberNicholas Butler21-May-05 17:50 
Generaldoes not work with VS2005beta2 Pin
MP3Observer20-May-05 1:32
memberMP3Observer20-May-05 1:32 
GeneralRe: does not work with VS2005beta2 Pin
Jonathan Merriweather20-May-05 20:26
memberJonathan Merriweather20-May-05 20:26 
GeneralRe: does not work with VS2005beta2 Pin
Nicholas Butler20-May-05 23:15
memberNicholas Butler20-May-05 23:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 26 May 2005
Article Copyright 2005 by Nicholas Butler
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid