Click here to Skip to main content
Click here to Skip to main content
Go to top

A Never-ending ProgressBar

, 30 Sep 2004
Rate this:
Please Sign up or sign in to vote.
A progress bar for when you don't know how long a process will take.

Sample screenshot

Introduction

Sometimes you just don’t know how long something will take. Like when your wife says she’ll only be a few minutes in the grocery store…you know what I mean.

The standard ProgressBar that ships with Visual Studio is great for when you know how long something will take or there is a way to determine just how many steps a process will have. But like the trip to the store with your wife, sometimes you just can’t know how long something’s going to take. That’s why I created this progress bar.

The code

The control is very simple in that all it does is use the standard Graphics methods to draw into a Rectangle object.

Private Sub OSProgressBar_Paint(ByVal sender As Object, _
         ByVal e As System.Windows.Forms.PaintEventArgs) _
         Handles MyBase.Paint
    Me._Graphics = e.Graphics
    Me._Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighSpeed

    'this stops some of the redraw flickering at higher speeds
    If _RequireClear Then
        Me._Graphics.Clear(Me.BackColor)
    End If

    DrawBackGround()
End Sub

Private Sub PositionIndicator(ByVal Rect As Rectangle)
    If Not IsNothing(Me._PointImage) AndAlso Me._ProgressType = _
                        OSProgressTypeConstants.osGRAPHICTYPE Then
        Me._Graphics.DrawImage(Me._PointImage, Rect)
    Else
        Select Case Me._ProgressBoxStyle
            Case OSProgressBoxStyleConstants.osSOLIDSAMESIZE
                Dim R2 As New Rectangle(Rect.Left + 3, _
                  Rect.Top + 3, Rect.Width - 5, Rect.Height - 5)
                Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
            Case OSProgressBoxStyleConstants.osBOXAROUND
                Me._Graphics.DrawRectangle(New Pen(_IndicatorColor), Rect)
                Dim R2 As New Rectangle(Rect.Left + 3, Rect.Top + 3, _
                                        Rect.Width - 5, Rect.Height - 5)
                Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
            Case OSProgressBoxStyleConstants.osSOLIDBIGGER
                Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), Rect)
            Case OSProgressBoxStyleConstants.osSOLIDSMALLER
                Dim R2 As New Rectangle(Rect.Left + 5, Rect.Top + 5, _
                                        Rect.Width - 9, Rect.Height - 9)
                Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
        End Select
    End If
End Sub

Private Sub DrawBackGround()
    Me._NumPoints = 0
    If Me.Width > 0 And Me.Height > 0 Then
        If Me._ShowBorder Then
            Me._Graphics.DrawRectangle(New Pen(SystemColors.ActiveBorder), _
                    New Rectangle(0, 0, Me.Width - 1, Me.Height - 1))
        End If
        Dim iBoxSize As Integer = Me.Height * 0.75
        Dim iBoxLeft As Integer = iBoxSize / 2
        If iBoxSize > 3 Then
            Do
                'entire area Rectangle for the background image
                Dim r As New Rectangle(iBoxLeft, 0, Me.Height - 1, Me.Height - 1)
                If r.Left + r.Width > Me.Width Then
                    Exit Do
                End If
                If Me._NumPoints = Me._Position Then
                    'draw position indicator in full rectagle
                    PositionIndicator(r)
                Else
                    'this will be the rectangle where 
                    'the background image is drawn
                    Dim R2 As New Rectangle(r.Left + 3, r.Top + 3, _
                                            r.Width - 6, r.Height - 6)
                    If Not IsNothing(Me._NormalImage) AndAlso Me._ProgressType = _
                                  OSProgressTypeConstants.osGRAPHICTYPE Then
                        Me._Graphics.DrawImage(Me._NormalImage, R2)
                    Else
                        Me._Graphics.FillRectangle(New SolidBrush(Me.ForeColor), R2)
                    End If
                End If
                iBoxLeft += (iBoxSize * 1.5)
                Me._NumPoints += 1
            Loop
        End If
    End If
End Sub

Private Sub OSProgressBar_Resize(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles MyBase.Resize
    Me._RequireClear = True
    'invalidate the control
    Me.Invalidate()
End Sub

Private Sub tmrAutoProgress_Tick(ByVal sender As Object, _
       ByVal e As System.EventArgs) Handles tmrAutoProgress.Tick
    If Me._Position = Me._NumPoints - 1 Then
        If Me._ProgressStyle = OSProgressStyleConstants.osLEFTTORIGHT Then
            Me._Position = 0
        Else
            Me._Position -= 1
            Me._Increasing = False
        End If
    ElseIf Me._Position = 0 And Not Me._Increasing Then
        Me._Position += 1
        Me._Increasing = True
    Else
        If Me._Increasing Then
            Me._Position += 1
        Else
            Me._Position -= 1
        End If
    End If
    Me._RequireClear = False
    Me.Invalidate()
End Sub

The user can choose whether to have the standard boxes drawn in one of four types (same size as background box, smaller, larger, or smaller with a box around), or the user can select to use images (icons work best) for the background and position indicators.

Rectangle size and number of positions are determined by the height of the control when placed on a form. For instance, if the control is tall, there will be fewer rectangles, but they will be larger. Alternately, if it is short, more rectangles and smaller. Currently, the control will only operate properly when horizontal (width is greater than the height), but I don't think the code would be too difficult to modify for vertical operation.

For a box type progress bar, developers can set the BackGroundColor, the ForeGroundColor (color of the background boxes), the IndicatorColor (color of the position boxes). For a graphic type progress bar, NormalImage (background image) and PointImage (position image) images can be set.

Developers can determine if the control "autoprogresses", that is, if it changes position automatically until the developer stops it. If AutoProgress is enabled, two more properties come into play; AutoProgressSpeed and ProgressStyle. The speed is self explanatory, 1 is slow, 255 is fast. The ProgressStyle property determines that when the indicator reaches the last point, if it starts over at the first point, or turns around and heads back in the other direction. Of course, the developer can also set the position manually if so desired.

Just a note concerning display of progress type controls. If you have a long process that you don't control, the current thread may block during the process. I've found this to be so when serializing and deserializing classes. In this instance, any method you use that is running within the same thread will also be blocked. I've tried animated GIFs for this purpose, and they also stop animating when blocking occurs. It's necessary to spawn a new thread prior to calling the blocking function and then display the necessary progress indicator.

License

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

Share

About the Author

Greg Osborne

United States United States
Visual Basic Developer since version 1.0
Java web developer
Currently developing in vb and c#

Comments and Discussions

 
GeneralSuggestion PinmemberRay Cassick1-Jul-08 7:28 
GeneralRe: Suggestion PinmemberGreg Osborne1-Jul-08 10:59 
GeneralBrilliant! Pinmemberjeff branscum14-Sep-07 5:34 
GeneralRe: Brilliant! PinmemberGreg Osborne14-Sep-07 6:37 
GeneralUsing with a status form Pinmemberlozinakr27-Jul-07 9:49 
GeneralRe: Using with a status form PinmemberGreg Osborne30-Jul-07 5:21 
GeneralRe: Using with a status form Pinmemberlozinakr30-Jul-07 5:47 
GeneralMay need a separate thread Pinmemberrottenroddy24-Jul-07 9:21 
AnswerRe: May need a separate thread PinmemberGreg Osborne24-Jul-07 11:37 
GeneralRe: May need a separate thread PinmemberGreg Osborne30-Jul-07 5:24 
GeneralLook and feel... Pinmemberrw_architect13-Jun-07 3:43 
GeneralProgress bar only runs once PinmemberNjabulo Nxele31-May-07 1:01 
GeneralRe: Progress bar only runs once PinmemberGreg Osborne31-May-07 5:23 
GeneralRe: Progress bar only runs once PinmemberNjabulo Nxele31-May-07 20:41 
GeneralRe: Progress bar only runs once PinmemberGreg Osborne31-May-07 5:25 
GeneralRe: Progress bar only runs once PinmemberNjabulo Nxele31-May-07 21:37 
GeneralRe: Progress bar only runs once PinmemberGreg Osborne1-Jun-07 4:42 
GeneralThanks Pinmemberginxs30-May-07 8:10 
Questionasp.net or windows Pinmemberdsmportal10-Apr-07 7:40 
QuestionHow do I do.... Pinmemberpsychocoder.net17-Jan-07 8:39 
AnswerRe: How do I do.... PinmemberGreg Osborne17-Jan-07 9:47 
GeneralRe: How do I do.... Pinmemberpsychocoder.net17-Jan-07 9:59 
QuestionWhat Am I missing? Control does not remotely look like it should Pinmemberwgkwvl20-Nov-06 23:42 
AnswerRe: What Am I missing? Control does not remotely look like it should PinmemberGreg Osborne31-May-07 5:27 
GeneralRe: What Am I missing? Control does not remotely look like it should Pinmemberrw_architect13-Jun-07 3:42 

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.140922.1 | Last Updated 30 Sep 2004
Article Copyright 2004 by Greg Osborne
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid