Introduction
In this article, I will show how to make a Status Strip control that acts as your progress bar as well as keep all existing functionality for your Windows form.
My first attempt at doing this was to override the ToolStatusStripLabel
control, which was successful, however, it had a few flaws; firstly on loading the form, you had to manually resize the ToolStatusStripLabel
to match the size of the Status Strip if you wanted it to cover the whole width of the form. Secondly, if you wanted to have multiple labels (or other controls on your Status Strip), this would limit the size of the progress bar.
I then looked at overriding the Status Strip control and it turned out to actually be easier than I initially thought. And this allowed me to have a progress bar that covered the whole Status Strip as well as add multiple controls.
I also use a progressive colour painting of the progress bar using two colours and a LinearGradientBrush
. You would be able to replace this section of code to implement your own style of painting a progress bar, or use some of the other progress bar examples found on CodeProject.
Using the code
The code is pretty simple. You first need to crate a new control class that is based on the standard StatusStrip
control. We don’t want to reinvent the wheel and are really only interested in enhancing the existing control, so it’s a good base class.
public class ProgressStatusStrip : StatusStrip
{
}
Next, we add some new local variables which are used for the control enhancements. Two variables to store the colours of the progress bar, three variables to store the progress bar state. Note: You will notice I use FLOAT
s for these, the main reason is that the world is not whole, very rarely do you even need to complete a nice round number of tasks, so your progress incremented would normally be a float (example, 6 tasks, 100/6 = 16.66…67). As standard progress bars use an INT
for the Value
properties, you lose precision when incrementing your progress (unless you keep a separate variable in your code for the progress and just assign that to the progress bar in each iteration). So by using FLOAT
s, it takes some of the load of your main code to keep an accurate track of its progress.
#region ProgressStatusStrip Definitions
private Color _barColor = Color.ForestGreen;
private Color _barShade = Color.LightGreen;
private float _progressMin = 0.0F;
private float _progressMax = 100.0F;
private float _progressVal = 0.0F;
#endregion
Next, we add the public properties that we expose to the user, allowing them to configure the progress bar portion of the class at design and run time. It’s always nice to add descriptions for each property and categorise them so they don’t just get lost with the other control properties. We have five properties, two to control the colours of the progress bar, and three which control the progress bar state (these are a match to the properties you get with a standard progress bar). Note: It’s always best when a user changes a property value to do some data validation to ensure you don’t have any code issues elsewhere, hence the checking inside the Set functions.
#region ProgressStatusStrip Properties
[Description("The color of the Progress Bar"),
Category("Progress Bar"),
DefaultValue(typeof(Color), "Color.ForestGreen")]
public Color ProgressColor
{
get { return _barColor; }
set { _barColor = value; this.Invalidate(); }
}
[Description("The shade color of the Progress Bar"),
Category("Progress Bar"),
DefaultValue(typeof(Color), "Color.LightGreen")]
public Color ProgressShade
{
get { return _barShade; }
set { _barShade = value; this.Invalidate(); }
}
[Description("The lower bound of the range the Progress Bar is working with"),
Category("Progress Bar"), DefaultValue(0.0F)]
public float Minimum
{
get { return _progressMin; }
set
{
_progressMin = value;
if (_progressMin > _progressMax) _progressMax = _progressMin;
if (_progressMin > _progressVal) _progressVal = _progressMin;
this.Invalidate();
}
}
[Description("The upper bound of the range the Progress Bar is working with"),
Category("Progress Bar"), DefaultValue(100.0F)]
public float Maximum
{
get { return _progressMax; }
set
{
_progressMax = value;
if (_progressMax < _progressMin) _progressMin = _progressMax;
if (_progressMax < _progressVal) _progressVal = _progressMax;
this.Invalidate();
}
}
[Description("The current value for the Progress Bar, " +
"in the range specified by the minimum and maximum properties"),
Category("Progress Bar"), DefaultValue(0.0F)]
public float Value
{
get { return _progressVal; }
set
{
_progressVal = value;
if (_progressVal < _progressMin) _progressVal = _progressMin;
if (_progressVal > _progressMax) _progressVal = _progressMax;
this.Invalidate();
}
}
#endregion
The last stage is to override the OnPaint
method; this is where we handle the actual drawing of the progress bar. We calculate the actual progress as a percentage; if we’ve made no progress, there is nothing for us to do except call the base class' OnPaint
method which handles the drawing of the standard Status Strip parts. If we have made some progress, we need to draw the progress bar, we get the visible bounds of the Status Strip, and adjust this rectangle's width to match the amount of progress we need to show. Now we create a LinearGradientBrush
with the colours selected and then paint the progress area with this brush.
#region ProgressStatusStrip Methods
public ProgressStatusStrip() { }
protected override void OnPaint(PaintEventArgs pe)
{
float progPercent = (float)(_progressVal / (_progressMax - _progressMin));
if (progPercent > 0)
{
RectangleF progRectangle = pe.Graphics.VisibleClipBounds;
progRectangle.Width *= progPercent;
LinearGradientBrush progBrush = new LinearGradientBrush(
progRectangle, _barColor, _barShade, LinearGradientMode.Horizontal);
pe.Graphics.FillRectangle(progBrush, progRectangle);
progBrush.Dispose();
}
base.OnPaint(pe);
}
#endregion
How it works
Once you’ve compiled this code, you will be able to select the new control from the Toolbox to add to any form. Then just adjust the progress bar properties and update the Value
property of the ProgressStatusStrip
from your tasks.
Important note!
The most important thing you have to remember is that any controls added to your ProgressStatusStrip
must have their BackColor
set to Transparent
; otherwise they partially block the progress bar from being seen (as shown in the example code demo).
History
- 2011-07-14 - v1.0 - Article added.
- 2011-07-15 - v1.1 - Updated article, elaborated on how the code works.