vb.Net Progress Bar With Text

Updated Reverend Jim 4 Tallied Votes 79K Views Share

A long standing complaint with the standard progress bar control is that there is no easy way to display text. In spite of numerous requests, Microsoft has not included this capability. The following code includes a class, CustomProgress which inherits the standard ProgressBar and adds such a feature. It is fairly easy to use. If you want to show a percentage progress you set Text to a null string and the percentage will be calculated from the Minimum and Maximum value properties. If you want a custom string then assign it to Text. Either the percentge or custom text will be displayed when you call the Update method.

You can include the class code in your project, or if you are more adventurous, you can create a custom control and add it to your toolbox.

''                                                                                      
''  Name:                                                                               
''                                                                                      
''      TextProgressBar                                                                 
''                                                                                      
''  Description:                                                                        
''                                                                                      
''      Text code for a custom progress bar control. This extension to the standard     
''      progress bar allows for a text overlay that can display either a percentage     
''      complete value or any other custom string.                                      
''                                                                                      
''  Audit:                                                                              
''                                                                                      
''      2019-04-18  rj  Original code                                                   
''                                                                                      

Public Class Form1

    Private prgCopy As New CustomProgress

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.Controls.Add(prgCopy)
        prgCopy.Dock = DockStyle.Bottom
        prgCopy.Value = 0.0
        prgCopy.Minimum = 0.0
        prgCopy.Maximum = 100.0
        prgCopy.Style = ProgressBarStyle.Continuous

    End Sub

    Private Sub btnShowText_Click(sender As Object, e As EventArgs) Handles btnShowText.Click

        prgCopy.Text = "display any custom text"

        For i As Integer = 1 To 100
            System.Threading.Thread.Sleep(25)
            prgCopy.Value = i
            prgCopy.Update()
            My.Application.DoEvents()
        Next

    End Sub

    Private Sub btnShowPercent_Click(sender As Object, e As EventArgs) Handles btnShowPercent.Click

        prgCopy.Text = ""

        For i As Integer = 1 To 100
            System.Threading.Thread.Sleep(25)
            prgCopy.Value = i
            prgCopy.Update()
            My.Application.DoEvents()
        Next

    End Sub

End Class

''                                                                                      
''  Name:                                                                               
''                                                                                      
''      CustomProgress                                                                  
''                                                                                      
''  Description:                                                                        
''                                                                                      
''      ProgressBar that allows display of custom text or percentage progress.          
''                                                                                      
''  Custom Properties:                                                                  
''                                                                                      
''      Text:     String    If Null then % progress is calculated and displayed, else   
''                the value of the string is displayed.                                 
''                                                                                      
''  Audit:                                                                              
''                                                                                      
''      2019-04-18  rj  Original Code                                                   
''                                                                                      

Public Class CustomProgress

    Inherits ProgressBar

    Public Overrides Property Text As String

    Private Const WmPaint = 15

    'WndProc receives all messages directed to the current window. In order to
    'avoid overwriting your text, make sure the default code executes first,
    'then call the custom routine to display the overlid text.

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If m.Msg = WmPaint Then PaintText()
    End Sub

    Private Sub PaintText()

        Dim s As String = Text

        'Display either a percentage or custom text

        If s = "" Then
            Dim percent = CInt((Value - Minimum) * 100 / (Maximum - Minimum))
            s = percent.ToString & "%"
        End If

        'Get the graphics object and calculate drawing parameters based on the current Font specs

        Using g = Me.CreateGraphics()
            Dim textSize = g.MeasureString(s, Me.Font)
            Using b = New SolidBrush(ForeColor)
                g.DrawString(s, Me.Font, Brushes.Black, Me.Width / 2 - textSize.Width / 2, Me.Height / 2 - textSize.Height / 2)
            End Using
        End Using

    End Sub

End Class
tinstaafl 1,176 Posting Maven

Nice code. I'd like to point out a couple of things though:

The code converting the progressbar value to a percentage string can be simplified by using integer division and interpolated string syntax:

            Dim percent = ((Value - Minimum) * 100) \ (Maximum - Minimum)
            s = $"{percent}%"

In the nested Using block you don't seem to be using the brush you create anywhere inside the block:

            Using b = New SolidBrush(ForeColor)
                g.DrawString(s, Me.Font, Brushes.Black, Me.Width / 2 - textSize.Width / 2, Me.Height / 2 - textSize.Height / 2)
            End Using
Reverend Jim 4,678 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

The second one (unused b) was leftover code from previous attempts while figuring the current version out. I just neglected to remove it. Thanks for noting what could be improved.

TheZ 0 Newbie Poster

Scored 9 by me Sir..
Nice looking PeeBar..haha..

Mark@SF 0 Newbie Poster

Hi RJ -

I would like to use your CustomProgress control with a StatusStrip control during design-time (via the IDE). Can you show me how to add the CustomProgress control to the StatusStrip control’s drop-down list of controls?

This would allow me to use your CustomProgress control instead of the standard ProgressBar control with the StatusStrip control on my form. Thanks.

Reverend Jim 4,678 Hi, I'm Jim, one of DaniWeb's moderators. Moderator Featured Poster

As I recall (it's been a while) you right click on the toolbox and select Choose items then browse to whatever custom control you want to include. In my case I didn't actually create a custom control that can be used this way. I just subclassed the existing control and added a bit of functionality. You could just put the code in a module and include or copy it into an existing project.

Mark@SF 0 Newbie Poster

Hello RJ -

This is what I was able to create as a solution to my inquery..

2020-04-05_20-31-36.png

Here's what I have put together (it may not be the "best" approach, so I'd appreciate it if you have any suggestions)...

'   https://stackoverflow.com/questions/7608556/how-to-create-custom-toolstripprogressbar-in-c-sharp-windows-forms

Imports System.Windows.Forms.Design '...required for ToolStripItemDesignerAvailability

<ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip Or ToolStripItemDesignerAvailability.StatusStrip)>
Public Class ToolStripProgressBarC
    Inherits MyCustomToolStripControlHost

    '...call the base constructor passing in a myCustomProgressBar instance
    Public Sub New()
        MyBase.New(New myCustomProgressBar)
        CType(Control, myCustomProgressBar).Style = ProgressBarStyle.Continuous
    End Sub

    Public ReadOnly Property ProgressBarControl As myCustomProgressBar
        Get
            Return CType(Control, myCustomProgressBar)
        End Get
    End Property

    '...expose the myCustomProgressBar.Value as a property
    Public Property Value As Integer
        Get
            Return Me.ProgressBarControl.Value
        End Get
        Set
            Me.ProgressBarControl.Value = Value
        End Set
    End Property
End Class

Public Class MyCustomToolStripControlHost
    Inherits ToolStripControlHost

    Public Sub New()
        MyBase.New(New Control())
    End Sub

    Public Sub New(ByVal c As Control)
        MyBase.New(c)
    End Sub
End Class

Public Class myCustomProgressBar

    '   https://www.daniweb.com/programming/software-development/code/519610/vb-net-progress-bar-with-text

    Inherits ProgressBar

    Public Overrides Property Text As String
    '...http://www.pinvoke.net/default.aspx/Constants/WM.html
    '   WM_PAINT = &HF  decimal value = 15...CDec("&H0F") = 15
    Private Const WmPaint = 15

    '...WndProc receives all messages directed to the current window. In order to
    '   avoid overwriting your text, make sure the default code executes first,
    '   then call the custom routine to display the overlaid text

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If m.Msg = WmPaint Then
            PaintText()
        End If
    End Sub

    Private Sub PaintText()

        Dim s As String = Text

        '...display either a percentage or custom text

        If s = "" Then
            Dim percent = CInt(100 * (Value - Minimum) / (Maximum - Minimum))
            s = percent.ToString & "%"
        End If

        '...get the graphics object and calculate drawing parameters based on the current Font specs

        Using g As Graphics = Me.CreateGraphics()
            Dim textSize As SizeF = g.MeasureString(s, Me.Font)
            Using b = New SolidBrush(ForeColor)
                g.DrawString(s, Me.Font, Brushes.Black, CSng(Me.Width / 2 - textSize.Width / 2), CSng(Me.Height / 2 - textSize.Height / 2))
            End Using
        End Using

    End Sub

End Class

Thank you again for your help!

Mark@SF 0 Newbie Poster

RJ -

Can you tell me what is the purpose of the following statement in this code snippet?

<ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip Or ToolStripItemDesignerAvailability.StatusStrip)>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.