Click here to Skip to main content
15,881,852 members
Articles / Programming Languages / C#
Article

Indeterminate or Bouncing Progress Bar

Rate me:
Please Sign up or sign in to vote.
2.00/5 (5 votes)
4 Dec 20042 min read 66.7K   682   20   5
This is a beginning of XP's bouncing progress bar in C#.

Sample Image - screenshot.jpg

Introduction

After searching for many hours for the bouncing control bar you see in XP, I found this seemingly necessary control missing. So never having created a custom control before, I set out to do just that. My experience in .NET is limited, my time developing the control was limited, but my enthusiasm was not. Here is the result.

Special thanks to Microsoft for their introduction in the article HOW TO: Create a Smooth Progress Bar in Visual C# .NET.

I will only go over the main points as I expect everyone is familiar with programming....

When we update the value (which is automatically done by a forms timer), we need to see if it has gone to the edge of our control. This is determined base on the style of progressbar you selected. When it has gone as far as it can go, it goes the other way.

C#
if (increasing)
{
  val++;
}
else
{
  val--;
}
//int oldValue = val;
// Make sure that the value does not stray outside the valid range.
if (val < min)
{
  val = min;
  increasing = true;
}
else if ((style == LocTecBarStyle.SmoothBounce) && (val > (max - blockWidth)))
{
  val = (max - blockWidth);
  increasing = false;
}
else if ((style == LocTecBarStyle.BlockBounce) && 
      (val > (max - (blockWidth * 2) - blockSpace)))
{
  val = (max - (blockWidth * 2) - blockSpace);
  increasing = false;
}

Next, we set up the area to invalidate. This is to minimize flickering. For a smooth progress bar we only invalidate a total width of two pixels. For the block style we invalidate a width of four pixels. This causes Windows to redraw those areas.

C#
Rectangle invalidateLeftArea = this.ClientRectangle;
Rectangle invalidateRightArea = this.ClientRectangle;
Rectangle invalidateInnerLeftArea = this.ClientRectangle;
Rectangle invalidateInnerRightArea = this.ClientRectangle;
invalidateLeftArea.Width = 1;
invalidateRightArea.Width = 1;
invalidateInnerLeftArea.Width = 1;
invalidateInnerRightArea.Width = 1;
if (increasing)
{
  invalidateLeftArea.X = (val - 1);
  invalidateRightArea.X = (val + blockWidth - 1);
  if (style == LocTecBarStyle.BlockBounce)
  {
    invalidateRightArea.X = (val + (blockWidth * 2) + blockSpace - 1);
    invalidateInnerLeftArea.X = (val + blockWidth - 1);
    invalidateInnerRightArea.X = (val + blockWidth + blockSpace - 1);
  }
}
else
{
  invalidateRightArea.X = (val + blockWidth);
  invalidateLeftArea.X = (val);
  if (style == LocTecBarStyle.BlockBounce)
  {
    invalidateRightArea.X = (val + (blockWidth * 2) + blockSpace);
    invalidateInnerRightArea.X = (val + blockWidth + blockSpace);
    invalidateInnerLeftArea.X = (val + blockWidth);
  }
}
// Invalidate the intersection region only.
this.Invalidate(invalidateLeftArea);
this.Invalidate(invalidateRightArea);
if (style == LocTecBarStyle.BlockBounce)
{
  this.Invalidate(invalidateInnerLeftArea);
  this.Invalidate(invalidateInnerRightArea);
}

In the OnPaint event, we draw the rectangles. For the block style, we use the gradient for a true XP feel. There is a problem with it where (depending on the height of the control) it sometimes leaves a one pixel line between the gradients. If you know why, let me know. If I find out why, I will post the update.

C#
Graphics g = e.Graphics;
SolidBrush brush = new SolidBrush(BarColor);
SolidBrush spaceBrush = new SolidBrush(this.BackColor);
float percent = (float)(val - min) / (float)(max - min);
switch (style)
{
  case (LocTecBarStyle.SmoothBounce):
  {
    Rectangle rect = this.ClientRectangle;
    // Set the area for drawing the progress.
    rect.Width = blockWidth;
    // Set the new location of the block
    rect.X = val;
    // Draw the progress meter.
    g.FillRectangle(brush, rect);
    break;
  }
  case (LocTecBarStyle.BlockBounce):
  {
    Rectangle gradientTop = this.ClientRectangle;
    Rectangle gradientBottom = this.ClientRectangle;
    Rectangle space = this.ClientRectangle;
    // Set the Width for drawing the progress.
    gradientTop.Width = (blockWidth * 2) + blockSpace;
    gradientBottom.Width = (blockWidth * 2) + blockSpace;
    space.Width = blockSpace;
    // Height
    gradientTop.Height = (int)(ClientRectangle.Height * .5) - 1;
    //(int)(ClientRectangle.Height * .5);
    gradientBottom.Height = ClientRectangle.Height - gradientTop.Height; 
    // Top
    gradientTop.Y = ClientRectangle.Y;
    gradientBottom.Y = gradientTop.Bottom;
    // Left
    gradientTop.X = val;
    gradientBottom.X = val;

    space.X = val + blockWidth;
    // Gradient
    LinearGradientMode lgmTop = LinearGradientMode.Vertical;
    using (LinearGradientBrush lgbTop = 
       new LinearGradientBrush(gradientTop, this.BackColor, BarColor, lgmTop))
    g.FillRectangle(lgbTop, gradientTop);
    LinearGradientMode lgmBottom = LinearGradientMode.Vertical;
    using (LinearGradientBrush lgbBottom = 
       new LinearGradientBrush(gradientBottom, BarColor, this.BackColor, lgmBottom))
    g.FillRectangle(lgbBottom, gradientBottom);
    // Draw the progress meter.
    g.FillRectangle(spaceBrush, space);
    break;
  }
}
// Draw a three-dimensional border around the control.
Draw3DBorder(g);
// Clean up.
brush.Dispose();
g.Dispose();

I have not optimized, perfected nor managed properly this code. I am open to criticisms, opinions, ideas, suggestions, etc. One last mention. If you are performing an intense task you will want to put that task in a separate thread so that this control can update its interface.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
rjn
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalnice activity bar Pin
BillW338-Jun-11 5:46
professionalBillW338-Jun-11 5:46 
GeneralActivity Bar Pin
kentcb12-Dec-04 14:15
kentcb12-Dec-04 14:15 
GeneralBouncing progress bar. Pin
John howell5-Dec-04 19:15
John howell5-Dec-04 19:15 
GeneralRe: Bouncing progress bar. Pin
rjn6-Dec-04 5:07
rjn6-Dec-04 5:07 
GeneralSimilar control (with XP Visual Styles) Pin
ebukiet24-Dec-04 17:09
ebukiet24-Dec-04 17:09 

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.