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

ProgressBar with Percentage

, 3 Nov 2009
Rate this:
Please Sign up or sign in to vote.
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

Introduction

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.

Background

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
    Get
        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
    Get
        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
    Get
        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
    Get
        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
    Get
        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
    Get
        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
    Get
        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
    Get
        Return MyBase.Font
    End Get
    Set(ByVal value As Font)
        MyBase.Font = value
    End Set
End Property

Example

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

progbarwithpercentage.gif

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)
    reg2.Exclude(reg1)

    ' 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)

    reg1.Dispose()
    reg2.Dispose()
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

History

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

License

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

Share

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 identi.ca [3].
 
[0] http://www.jeroendedauw.com/
[1] http://blog.bn2vs.com/
[2] https://twitter.com/#!/JeroenDeDauw
[3] http://identi.ca/jeroendedauw
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 1 Pinmemberpeymanshams7-Dec-10 9:21 
GeneralXP BUG Pinmemberbn2vs29-Mar-09 2:57 
GeneralRe: XP BUG Pinmemberrootjumper1-Nov-09 20:22 
GeneralRe: XP BUG Pinmemberjeroen de dauw2-Nov-09 1:46 
GeneralRe: XP BUG Pinmemberjeroen de dauw2-Nov-09 6:15 
GeneralAnother Thank You PinmemberDean Slindee18-Mar-09 16:40 
GeneralRe: Another Thank You Pinmemberbn2vs20-Mar-09 5:57 
GeneralRe: Another Thank You Pinmemberdslindee20-Mar-09 14:44 
GeneralRe: Another Thank You Pinmemberbn2vs21-Mar-09 17:51 
GeneralThank you! Pinmemberakirilov12-Mar-09 5:34 
GeneralRe: Thank you! Pinmemberbn2vs12-Mar-09 9:10 
Generalmanifest missing Pinmemberrspercy5811-Mar-09 23:04 
GeneralRe: manifest missing Pinmemberbn2vs12-Mar-09 9:11 
GeneralRe: manifest missing Pinmemberrspercy5812-Mar-09 12:35 
GeneralRe: manifest missing Pinmemberbn2vs12-Mar-09 21:54 
GeneralRe: manifest missing Pinmemberrspercy5812-Mar-09 23:48 
GeneralRe: manifest missing Pinmemberbn2vs13-Mar-09 12:23 
GeneralRe: manifest missing Pinmemberrspercy5813-Mar-09 15:22 
GeneralRe: manifest missing Pinmemberrspercy5813-Mar-09 15:56 
GeneralGraphics object. PinmvpDaveyM699-Mar-09 9:59 
GeneralRe: Graphics object. [modified] Pinmemberbn2vs10-Mar-09 8:11 
GeneralRe: Graphics object. PinmvpDaveyM6911-Mar-09 2:39 
GeneralStripped C# port [modified] PinmvpDaveyM6911-Mar-09 4:14 
GeneralRe: Stripped C# port Pinmemberbn2vs11-Mar-09 5:25 

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
Web02 | 2.8.140922.1 | Last Updated 3 Nov 2009
Article Copyright 2009 by Jeroen De Dauw
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid