How to create a smooth ProgressBar in Visual C++ 2005 or in Visual C++ .NET

For a Microsoft Visual Basic .NET version of this article, see
323088 .
For a Microsoft Visual C# .NET version of this article, see
323116 .

This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System::ComponentModel
  • System::Collections
  • System::Windows::Forms
  • System::Data
  • System::Drawing

IN THIS TASK

Summary

This article describes how to create a simple, custom UserControl class to create a smooth, scrolling ProgressBar control.

In earlier versions of the ProgressBar control, such as the version that is provided with the Microsoft Windows Common Controls ActiveX control, you can view the progress in two different views. To control these views, you use the Scrolling property that includes standard and smooth settings. Smooth scrolling produces a solid block of color that represents the progress, and standard scrolling appears segmented and is made up of a series of small blocks or rectangles. The ProgressBar control that is included with Microsoft Visual C++ 2005 or with Microsoft Visual C++ .NET supports only the standard setting.

The sample code in this article describes how to create a control that supports the following properties:
  • Minimum: This property obtains or sets the lower value for the range of valid values for progress. The default value of this property is zero (0); you cannot set this property to a negative value.
  • Maximum: This property obtains or sets the upper value for the range of valid values for progress. The default value of this property is 100.
  • Value: This property obtains or sets the current level of progress. The value must be in the range that the Minimum and the Maximum properties define.
  • ProgressBarColor: This property obtains or sets the color of the progress bar.
Back to the top

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Visual Studio 2005 or Microsoft Visual Studio .NET 2003
  • Microsoft .NET Framework 1.1 or later
This article assumes that you are familiar with the following topics:
  • Creating controls by using Microsoft Visual C++ 2005 or Microsoft Visual C++ .NET 2003
Back to the top

Create a custom ProgressBar control

  1. Start Microsoft Visual Studio 2005 or Microsoft Visual Studio .NET 2003.
  2. On the File menu, point to
    New, and then click Project.
  3. Click Visual C++ Projects under
    Project Types, and then click Windows Control Library (.NET) under Templates.

    Note In Visual Studio 2005, click Visual C++ under
    Project Types, and then click Windows Forms Console Library under Templates.
  4. In the Name box, type
    SmoothProgressBar, and then click
    OK.
  5. Typically, you inherit the newly created UserControl class (SmoothProgressBarControl class) from the ProgressBar class, and then you add the additional functionality to extend the existing ProgressBar control. However, the ProgressBar class is a sealed class and cannot be inherited. Therefore, you must build the control from the beginning. To do this, follow these steps:
    1. On the View menu, click
      Code to open the code editor.
    2. Add the following member variable declarations for holding the property values to the SmoothProgressBar class before the constructor function.
      // Minimum value for progress range
      int minimum;
      // Maximum value for progress range
      int maximum;
      // Current progress
      int value;
      // Color of progress meter
      Color progressBarColor;
    3. Add the following code to initialize the member variables in the constructor function after the InitializeComponent statement.
      minimum = 0;
      maximum = 100;
      value = 0;
      progressBarColor = Color::Blue;
    4. Add the following property getter and setter functions after the InitializeComponent function in the SmoothProgressBarControl class.
      public:
      __property int get_Minimum()
      {
      return minimum;
      }
      __property void set_Minimum(int NewMinimum)
      {
      // Prevent a negative value.
      if (NewMinimum < 0)
      {
      minimum = 0;
      }

      // Make sure that the minimum value is never set higher than the maximum value.
      if (NewMinimum > maximum)
      {
      minimum = NewMinimum;
      }

      // Ensure value is still in range
      if (value < minimum)
      {
      value = minimum;
      }

      // Invalidate the control to get a repaint.
      this->Invalidate();
      }

      __property int get_Maximum()
      {
      return maximum;
      }

      __property void set_Maximum(int NewMaximum)
      {
      // Make sure that the maximum value is never set lower than the minimum value.
      if (NewMaximum < minimum)
      {
      minimum = NewMaximum;
      }

      maximum = NewMaximum;

      // Make sure that value is still in range.
      if (value > maximum)
      {
      value = maximum;
      }

      // Invalidate the control to get a repaint.
      this->Invalidate();
      }

      __property int get_Value()
      {
      return value;
      }

      __property void set_Value(int NewValue)
      {
      int oldValue = value;

      // Make sure that the value does not stray outside the valid range.
      if (NewValue < minimum)
      {
      value = minimum;
      }
      else if (NewValue > maximum)
      {
      value = maximum;
      }
      else
      {
      value = NewValue;
      }

      // Invalidate only the changed area.
      float percent;

      Rectangle newValueRect = this->ClientRectangle;
      Rectangle oldValueRect = this->ClientRectangle;

      // Use a new value to calculate the rectangle for progress.
      percent = (float)(value - minimum) / (float)(maximum - minimum);
      newValueRect.Width = (int)((float)newValueRect.Width * percent);

      // Use an old value to calculate the rectangle for progress.
      percent = (float)(oldValue - minimum) / (float)(maximum - minimum);
      oldValueRect.Width = (int)((float)oldValueRect.Width * percent);

      Rectangle updateRect;

      // Find only the part of the screen that must be updated.
      if (newValueRect.Width > oldValueRect.Width)
      {
      updateRect.X = oldValueRect.Size.Width;
      updateRect.Width = newValueRect.Width - oldValueRect.Width;
      }
      else
      {
      updateRect.X = newValueRect.Size.Width;
      updateRect.Width = oldValueRect.Width - newValueRect.Width;
      }

      updateRect.Height = this->Height;

      // Invalidate the intersection region only.
      this->Invalidate(updateRect);
      }

      __property Color get_ProgressBarColor()
      {
      return progressBarColor;
      }

      __property void set_ProgressBarColor(Color NewColor)
      {
      progressBarColor = NewColor;
      // Invalidate the control to get a repaint.
      this->Invalidate();
      }
      Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:
      1. Click Project, and then click
        <ProjectName> Properties.

        Note <ProjectName> is a placeholder for the name of the project.
      2. Expand Configuration Properties, and then click General.
      3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click
        Apply, and then click OK.
      For more information about the common language runtime support compiler option, visit the following Microsoft Web site:
      /clr (Common Language Runtime Compilation)
      http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx
    5. Add the following code that handles the display of the ProgressBar control after the property getter and setter functions that you added in the previous step.
      protected:

      void OnResize(EventArgs *e)
      {
      // Invalidate the control to get a repaint.
      this->Invalidate();
      }

      void OnPaint(PaintEventArgs *e)
      {
      Graphics *g = e->Graphics;
      SolidBrush * brush = new SolidBrush(progressBarColor);
      float percent = (float)(value - minimum) / (float)(maximum - minimum);
      Rectangle rect = this->ClientRectangle;

      // Calculate area for drawing the progress.
      rect.Width = (int)((float)rect.Width * percent);

      // Draw the progress meter.
      g->FillRectangle(brush, rect);

      // Draw a three-dimensional border around the control.
      Draw3DBorder(g);

      // Clean up.
      brush->Dispose();
      g->Dispose();
      }

      private:

      void Draw3DBorder(Graphics *g)
      {
      int PenWidth = (int)Pens::White->Width;

      g->DrawLine(Pens::DarkGray,
      Point(this->ClientRectangle.Left , this->ClientRectangle.Top),
      Point((int)(this->ClientRectangle.Width) - PenWidth, this->ClientRectangle.Top));
      g->DrawLine(Pens::DarkGray,
      Point(this->ClientRectangle.Left, this->ClientRectangle.Top),
      Point(this->ClientRectangle.Left, (int)(this->ClientRectangle.Height) - PenWidth));
      g->DrawLine(Pens::White,
      Point(this->ClientRectangle.Left, (int)(this->ClientRectangle.Height) - PenWidth),
      Point((int)(this->ClientRectangle.Width) - PenWidth, (int)(this->ClientRectangle.Height) - PenWidth));
      g->DrawLine(Pens::White,
      Point((int)(this->ClientRectangle.Width) - PenWidth, this->ClientRectangle.Top),
      Point((int)(this->ClientRectangle.Width) - PenWidth, (int)(this->ClientRectangle.Height) - PenWidth));
      }
  6. Press the CTRL+SHIFT+S key combination to save the project.
  7. Press the CTRL+SHIFT+B key combination to build the solution.

    This builds the SmoothProgressBarControl UserControl class and creates a dynamic link library (DLL) file.
  8. On the File menu, click Close Solution to quit the project.
Back to the top

Create a sample client application

  1. On the File menu, point to
    New, and then click Project.
  2. Click Visual C++ Projects under
    Project Types, and then click Windows Forms Application (.NET) under Templates.
  3. In the Name box, type
    ProgressBar, and then click
    OK.

    By default, the Form1 form is created and opens in Design mode.
  4. To add two instances of the SmoothProgressBarControl control to the form, follow these steps:
    1. On the Tools menu, click
      Add/Remove Toolbox Items.
    2. On the .NET Framework Components tab, click Browse, and then locate the
      SmoothProgressBar.dll file that you created in the
      Create a custom ProgressBar control section.
    3. Click OK. Notice that the SmoothProgressBarControl control is added to the toolbox.
    4. Add two instances of the SmoothProgressBarControl control to Form1.
  5. Add a Timer control to Form1.
  6. Right-click the timer1 control that is shown separately at the bottom of the designer window, and then click
    Properties.
  7. Click the Events button, and then double-click the Tick event to add a timer1_Tick event handler to the code.
  8. Add the following code in the timer1_Tickevent handler.
    if (this->smoothProgressBarControl1->Value > 0)
    {
    this->smoothProgressBarControl1->Value--;
    this->smoothProgressBarControl2->Value++;
    }
    else
    {
    this->timer1->Enabled = false;
    }
  9. On the View menu, click
    Designer to switch to Design mode.
  10. Add a Button control to Form1.
  11. Double-click button1 to add a
    button1_Click event handler to the code.
  12. Add the following code in the
    button1_Click event handler:
    this->smoothProgressBarControl1->Value = 100;
    this->smoothProgressBarControl2->Value = 0;

    this->timer1->Interval = 1;
    this->timer1->Enabled = true;
  13. Press the CTRL+SHIFT+S key combination to save the project.
  14. Press the CTRL+SHIFT+B key combination to build the solution.
  15. Press the CTRL+F5 key combination to run the project.
  16. Click button1. Notice that the two progress indicators display the progress in a smooth manner. One progress indicator displays the progress in an increasing manner, and the other progress indicator displays the progress in a decreasing or a countdown manner.
Back to the top

References

For more information about the ProgressBar class, visit the following Microsoft Developer Network (MSDN) Web site:Back to the top
Propriedades

ID do Artigo: 816195 - Última Revisão: 7 de dez de 2007 - Revisão: 1

Comentários