Click here to Skip to main content
15,067,839 members
Articles / Programming Languages / Visual Basic
Posted 8 Mar 2009


92 bookmarked

ProgressBar with Percentage

Rate me:
Please Sign up or sign in to vote.
4.48/5 (23 votes)
3 Nov 2009GPL33 min read
Component that extends the native .NET progress bar with percentage properties and the ability to display it in the progress bar.
pbarWithPercentageDemo.gif pbarWithPercentageDemo.gif


This class extends the native .NET progress bar with a percentage property that can be displayed inside the progress bar, and is used to get or set the value of the bar itself. The text can be aligned with the Alignment property and also has Font and Padding properties to allow further customization. On top of this, you can change the color of the percentage that is in the colored part of the progress bar.

Why ANOTHER progress bar control, you might ask yourself. Simple. Before creating this control, I did quite some research into finding a control that enabled displaying a percentage in a progress bar. Most of them succeeded in doing this with varying degrees of customization options, and worked fine in Windows XP. However, once using it on a Vista, the percentage would get deleted because the bar continuously redraws itself. This control will automatically redraw the percentage when the bar is refreshed.


This class contains a lot of code based upon work by people on VB.NET forums. Go to this thread for more information. I am using this component in multiple VB.NET applications without any problems, and it should work in projects in other .NET languages.

Using the Code

Once you added the class to your project, you should be able to add the new component to your forms with the designer or do it manually with code.

Here you have an overview of properties that have been added:

<Browsable(True), Category("Appearance"), _
	Description("The percentage of the progressbar")> _
Public Property Percentage() As Double
        Return Me.Value / Me.Maximum * 100
    End Get
    Set(ByVal value As Double)
        If value >= 0 And value <= 100 Then
            Me.Value = CInt(Me.Maximum * value / 100)
            If Me.PercentageVisible And Me.AutoUpdatePercentage _
			Then Me.ShowPercentage()
        End If
    End Set
End Property
<Browsable(True), Category("Appearance"), DefaultValue(0), _
	Description("Gets or sets the amount of decimals that will _
	be displayed in the percentage")> _
Public Overridable Property PercentageDecimals() As Int32
        Return m_decimals
    End Get
    Set(ByVal value As Int32)
        If value > -1 Then m_decimals = value
    End Set
End Property
<Browsable(True), Category("Appearance"), DefaultValue(True), _
	Description("Gets or sets if the percentage should be visible")> _
Public Overridable Property PercentageVisible() As Boolean
        Return m_p_visible
    End Get
    Set(ByVal value As Boolean)
        If value <> Me.PercentageVisible Then
            If Not value Then Me.Graphics.Clear(Color.Transparent)
            m_p_visible = value
            RaiseEvent PercentageVisibleChanged(Me, New EventArgs)
        End If
    End Set
End Property
<Browsable(True), Category("Appearance"), DefaultValue("MiddleCenter"), _
	Description("Gets or sets if the percentage alignment")> _
Public Overridable Property PercentageAlign() As ContentAlignment
        Return m_p_align
    End Get
    Set(ByVal value As ContentAlignment)
        m_p_align = value
    End Set
End Property
<Browsable(True), Category("Appearance"), _
	Description("Gets or sets the color of the percentage text _
	at the place of the progressbar that is indicated")> _
Public Overridable Property OverLayColor() As Color
        Return m_overLayFont
    End Get
    Set(ByVal value As Color)
        m_overLayFont = value
    End Set
End Property
<Browsable(True), Category("Behavior"), DefaultValue(True), _
	Description("Gets or sets if the percentage should be auto updated")> _
Public Overridable Property AutoUpdatePercentage() As Boolean
        Return m_auto_update
    End Get
    Set(ByVal value As Boolean)
        m_auto_update = value
    End Set
End Property
<Browsable(True), Category("Layout"), _
	Description("Gets or sets if the interior spacing of the control")> _
Public Overridable Overloads Property Padding() As Padding
        Return MyBase.Padding
    End Get
    Set(ByVal value As Padding)
        MyBase.Padding = value
    End Set
End Property
<Browsable(True), Category("Appearance"), _
	Description("Gets or sets the font of the percentage text")> _
Public Overridable Overloads Property Font() As Font
        Return MyBase.Font
    End Get
    Set(ByVal value As Font)
        MyBase.Font = value
    End Set
End Property


A simple example of setting a few properties:

With Me.ProgressbarWithPercentage1
    .ForeColor = Drawing.Color.DimGray ' Color of the text not in the colored part
    .OverLayColor = Drawing.Color.Black ' Color of the text in the colored part
    .PercentageAlign = Drawing.ContentAlignment.MiddleLeft ' Alignment of the text
    .Padding = New Windows.Forms.Padding(20, 0, 0, 0) ' Padding of the text
End With


Inside the Component

Now how does it actually work? I'll try to give you a reasonable understanding.

The most important method is the ShowText method, which draws a string onto the progress bar. This method can be used to draw any string, but is internally only used to draw the percentage.

Public Sub ShowText(ByVal text As String)
    ' Determine the areas for the ForeColor and OverlayColor
    Dim r1 As RectangleF = Me.ClientRectangle
    r1.Width = CSng(r1.Width * Me.Value / Me.Maximum)
    Dim reg1 As New Region(r1)
    Dim reg2 As New Region(Me.ClientRectangle)

    ' Draw the string
    Me.Graphics.Clip = reg1
    Me.Graphics.DrawString(text, Me.Font, New SolidBrush(Me.OverLayColor), _
		Me.DrawingRectangle, m_strFormat)
    Me.Graphics.Clip = reg2
    Me.Graphics.DrawString(text, Me.Font, New SolidBrush(Me.ForeColor), _
	Me.DrawingRectangle, m_strFormat)

End Sub

This method is used by the ShowPercentage method in a pretty straight forward way:

Public Sub ShowPercentage()
    Me.ShowText(Math.Round(Me.Percentage, _
	Me.PercentageDecimals).ToString & "%")
End Sub

The rectangle to draw in is determined every time the control is resized and every time the padding is changed with the following code:

Private Sub setDrawingRectangle()
    ' Determine the coordinates and size of the drawing rectangle
	' depending on the progress bar size and padding
    Me.DrawingRectangle = New RectangleF(Me.Padding.Left, _
                                       Me.Padding.Top, _
                                       Me.Width - Me.Padding.Left - Me.Padding.Right, _
                                       Me.Height - Me.Padding.Top - Me.Padding.Bottom)
        End Sub

Note that this property is used for every draw event. Another property used for every draw event is the stringformat. This is set every time you change the alignment.

Private Sub setStringFormat()
    ' Determine the horizontal alignment
    Select Case Me.PercentageAlign
        Case ContentAlignment.BottomCenter, _
		ContentAlignment.BottomLeft, ContentAlignment.BottomRight
                    m_strFormat.LineAlignment = StringAlignment.Far
        Case ContentAlignment.MiddleCenter, _
		ContentAlignment.MiddleLeft, ContentAlignment.MiddleRight
                    m_strFormat.LineAlignment = StringAlignment.Center
        Case ContentAlignment.TopCenter, _
		ContentAlignment.TopLeft, ContentAlignment.TopRight
                    m_strFormat.LineAlignment = StringAlignment.Near
    End Select

    ' Determine the vertical alignment
    Select Case Me.PercentageAlign
        Case ContentAlignment.BottomLeft, _
		ContentAlignment.MiddleLeft, ContentAlignment.TopLeft
                    m_strFormat.Alignment = StringAlignment.Near
        Case ContentAlignment.BottomCenter, _
		ContentAlignment.MiddleCenter, ContentAlignment.TopCenter
                    m_strFormat.Alignment = StringAlignment.Center
        Case ContentAlignment.BottomRight, _
		ContentAlignment.MiddleRight, ContentAlignment.TopRight
                    m_strFormat.Alignment = StringAlignment.Far
    End Select
End Sub


Changes in version 1.0.10

  • Added percentage format property, allowing you to use custom formats
  • Fixed XP bug, that caused the percentage not to be displayed properly
  • Created SourceForge project for SVN capabilities

Changes in version 1.0.9

  • Fixed a number of dispose issues (a LOT of thanks to JohnH for helping me with this!)
  • Fixed bug in percentage calculation when using multiple decimals
  • Added an auto increment function to the demo and added decimals to a few bars

Changes in version 1.0.6

  • Improved component efficiency by not recalculating some values for every draw event
  • Added multiple new events

Changes in version 1.0.5

  • Added extra documentation and events

Changes in version 1.0.4

  • Fixed alignment bug
  • Added padding property


This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


About the Author

Jeroen De Dauw
Software Developer
Belgium Belgium
I am a free and open source software enthusiast and freelance software developer with multiple years of experience in both web and desktop development. Currently my primarily focus is on MediaWiki and Semantic MediaWiki work. I'm in the all time top 10 MediaWiki comitters and am one of the WikiWorks consultants. You can contact me at jeroendedauw at gmail for development jobs and questions related to my work.

More info can be found on my website [0] and my blog [1]. You can also follow me on twitter [2] and [3].


Comments and Discussions

QuestionThe text is flickering. What could be causing this? Pin
Member 1153095511-Oct-15 23:53
MemberMember 1153095511-Oct-15 23:53 
GeneralMy vote of 1 Pin
peymanshams7-Dec-10 9:21
Memberpeymanshams7-Dec-10 9:21 
GeneralXP BUG Pin
Jeroen De Dauw29-Mar-09 2:57
MemberJeroen De Dauw29-Mar-09 2:57 
GeneralRe: XP BUG Pin
freakyit1-Nov-09 20:22
Memberfreakyit1-Nov-09 20:22 
GeneralRe: XP BUG Pin
Jeroen De Dauw2-Nov-09 1:46
MemberJeroen De Dauw2-Nov-09 1:46 
GeneralRe: XP BUG Pin
Jeroen De Dauw2-Nov-09 6:15
MemberJeroen De Dauw2-Nov-09 6:15 
GeneralAnother Thank You Pin
dslindee18-Mar-09 16:40
Memberdslindee18-Mar-09 16:40 
GeneralRe: Another Thank You Pin
Jeroen De Dauw20-Mar-09 5:57
MemberJeroen De Dauw20-Mar-09 5:57 
GeneralRe: Another Thank You Pin
dslindee20-Mar-09 14:44
Memberdslindee20-Mar-09 14:44 
GeneralRe: Another Thank You Pin
Jeroen De Dauw21-Mar-09 17:51
MemberJeroen De Dauw21-Mar-09 17:51 
GeneralThank you! Pin
akirilov12-Mar-09 5:34
Memberakirilov12-Mar-09 5:34 
GeneralRe: Thank you! Pin
Jeroen De Dauw12-Mar-09 9:10
MemberJeroen De Dauw12-Mar-09 9:10 
Generalmanifest missing Pin
rspercy6511-Mar-09 23:04
Memberrspercy6511-Mar-09 23:04 
GeneralRe: manifest missing Pin
Jeroen De Dauw12-Mar-09 9:11
MemberJeroen De Dauw12-Mar-09 9:11 
GeneralRe: manifest missing Pin
rspercy6512-Mar-09 12:35
Memberrspercy6512-Mar-09 12:35 
GeneralRe: manifest missing Pin
Jeroen De Dauw12-Mar-09 21:54
MemberJeroen De Dauw12-Mar-09 21:54 
GeneralRe: manifest missing Pin
rspercy6512-Mar-09 23:48
Memberrspercy6512-Mar-09 23:48 
GeneralRe: manifest missing Pin
Jeroen De Dauw13-Mar-09 12:23
MemberJeroen De Dauw13-Mar-09 12:23 
GeneralRe: manifest missing Pin
rspercy6513-Mar-09 15:22
Memberrspercy6513-Mar-09 15:22 
GeneralRe: manifest missing Pin
rspercy6513-Mar-09 15:56
Memberrspercy6513-Mar-09 15:56 
GeneralGraphics object. Pin
DaveyM699-Mar-09 9:59
professionalDaveyM699-Mar-09 9:59 
GeneralRe: Graphics object. [modified] Pin
Jeroen De Dauw10-Mar-09 8:11
MemberJeroen De Dauw10-Mar-09 8:11 
GeneralRe: Graphics object. Pin
DaveyM6911-Mar-09 2:39
professionalDaveyM6911-Mar-09 2:39 
GeneralStripped C# port [modified] PinPopular
DaveyM6911-Mar-09 4:14
professionalDaveyM6911-Mar-09 4:14 
GeneralRe: Stripped C# port Pin
Jeroen De Dauw11-Mar-09 5:25
MemberJeroen De Dauw11-Mar-09 5:25 

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.