Click here to Skip to main content
Click here to Skip to main content

Indeterminate or Bouncing Progress Bar

, 4 Dec 2004
Rate this:
Please Sign up or sign in to vote.
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.

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.

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.

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

Share

About the Author

rjn

United States United States
No Biography provided

Comments and Discussions

 
Generalnice activity bar PinmemberCIDev8-Jun-11 5:46 
GeneralActivity Bar Pinmemberkentcb12-Dec-04 14:15 
GeneralBouncing progress bar. PinmemberJohn howell5-Dec-04 19:15 
GeneralRe: Bouncing progress bar. Pinmemberrjn6-Dec-04 5:07 
GeneralSimilar control (with XP Visual Styles) Pinmemberebukiet24-Dec-04 17:09 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.141022.2 | Last Updated 4 Dec 2004
Article Copyright 2004 by rjn
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid