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

ProgressBar with Percentage

By , 3 Nov 2009
 
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)

About the Author

Jeroen De Dauw
Software Developer
Belgium Belgium
Member
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

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberpeymanshams7 Dec '10 - 9:21 
GeneralXP BUGmemberbn2vs29 Mar '09 - 2:57 
GeneralRe: XP BUGmemberrootjumper1 Nov '09 - 20:22 
GeneralRe: XP BUGmemberjeroen de dauw2 Nov '09 - 1:46 
GeneralRe: XP BUGmemberjeroen de dauw2 Nov '09 - 6:15 
GeneralAnother Thank YoumemberDean Slindee18 Mar '09 - 16:40 
GeneralRe: Another Thank Youmemberbn2vs20 Mar '09 - 5:57 
GeneralRe: Another Thank Youmemberdslindee20 Mar '09 - 14:44 
GeneralRe: Another Thank Youmemberbn2vs21 Mar '09 - 17:51 
GeneralThank you!memberakirilov12 Mar '09 - 5:34 
GeneralRe: Thank you!memberbn2vs12 Mar '09 - 9:10 
Generalmanifest missingmemberrspercy5811 Mar '09 - 23:04 
GeneralRe: manifest missingmemberbn2vs12 Mar '09 - 9:11 
GeneralRe: manifest missingmemberrspercy5812 Mar '09 - 12:35 
GeneralRe: manifest missingmemberbn2vs12 Mar '09 - 21:54 
GeneralRe: manifest missingmemberrspercy5812 Mar '09 - 23:48 
GeneralRe: manifest missingmemberbn2vs13 Mar '09 - 12:23 
GeneralRe: manifest missingmemberrspercy5813 Mar '09 - 15:22 
GeneralRe: manifest missingmemberrspercy5813 Mar '09 - 15:56 
GeneralGraphics object.mvpDaveyM699 Mar '09 - 9:59 
GeneralRe: Graphics object. [modified]memberbn2vs10 Mar '09 - 8:11 
GeneralRe: Graphics object.mvpDaveyM6911 Mar '09 - 2:39 
GeneralStripped C# port [modified]mvpDaveyM6911 Mar '09 - 4:14 
GeneralRe: Stripped C# portmemberbn2vs11 Mar '09 - 5:25 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 3 Nov 2009
Article Copyright 2009 by Jeroen De Dauw
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid