Introduction
The current winforms progressbar control does not include any customisable options or properties, and the control cannot be inherited so we have to code our own.
The MSDN example I followed was https://support.microsoft.com/en-us/kb/323088.
The above example uses a User Control, but I'd like to use a class control instead, if you decide then of course you can make a user control from within your project.
I wanted a progress bar control I could customize but also still be a progress bar instead of random shapes and styles one wouldn't usually use in an application (well professionally anyway).
Using the Code
This control was made using .NET Framework 4.0.
Ok let's go, start a new Visual Studio project and choose, Class Library, and name it appropriately.
Now in the solution explorer, right mouse click on the project name and select add reference, then from the .NET tab, add the following:
System
System.Drawing
System.Windows.Forms
Now let's Import and start coding. Add the following:
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Windows.Forms
Public Class Progress_bar : Inherits Control
Private min As Integer = 0
Private max As Integer = 100
Private val As Integer = 0
Public usegrad As Boolean = False
Public bkColor As Color = Color.Transparent
Public enBackColor As Boolean = False
Public BarColor As Color = Color.Blue
Public gradcolor1 As Color = Color.DeepSkyBlue
Public gradcolor2 As Color = Color.Blue
Dim HColor As Color = Color.WhiteSmoke
Dim hStyle As HatchStyle
Dim drawhBrush As Boolean = False
Dim hatchBackColor As Color = Color.Transparent Public drwLabel As Boolean = False
Public draw3D As Boolean = False
Public Sub New()
MyBase.New()
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
End Sub
Protected Overrides Sub OnCreateControl()
MyBase.OnCreateControl()
End Sub
Public Property Minimum() As Integer
Get
Return min
End Get
Set(ByVal Value As Integer)
If (Value < 0) Then
min = 0
End If
If (Value > max) Then
min = Value
min = Value
End If
If (Value < min) Then
val = min
End If
Me.Invalidate()
End Set
End Property
Public Property Maximum() As Integer
Get
Return max
End Get
Set(ByVal Value As Integer)
If (Value < min) Then
min = Value
End If
max = Value
If (val > max) Then
val = max
End If
Me.Invalidate()
End Set
End Property
Public Property Value As Integer
Get
Return val
End Get
Set(ByVal Value As Integer)
Dim oldvalue As Integer = val
If (Value < min) Then
val = min
ElseIf (Value > max) Then
val = max
Else
val = Value
End If
Dim newValueRect As Rectangle = Me.ClientRectangle
Dim oldValueRect As Rectangle = Me.ClientRectangle
Dim percent As Decimal
percent = (val - min) / (max - min)
newValueRect.Width = newValueRect.Width * percent
percent = (oldvalue - min) / (max - min)
oldValueRect.Width = oldValueRect.Width * percent
Dim updateRect As Rectangle = New Rectangle()
If (newValueRect.Width > oldValueRect.Width) Then
updateRect.X = oldValueRect.Size.Width
updateRect.Width = newValueRect.Width - oldValueRect.Width
Else
updateRect.X = newValueRect.Size.Width
updateRect.Width = oldValueRect.Width - newValueRect.Width
End If
updateRect.Height = Me.Height
Me.Invalidate(updateRect.X)
End Set
End Property
Public Property ProgressBarColor() As Color
Get
Return BarColor
End Get
Set(ByVal Value As Color)
BarColor = Value
Me.Invalidate()
End Set
End Property
Public Property GradientColor1() As Color
Get
Return gradcolor1
End Get
Set(ByVal value As Color)
gradcolor1 = value
Me.Invalidate()
End Set
End Property
Public Property GradientColor2() As Color
Get
Return gradcolor2
End Get
Set(ByVal value As Color)
gradcolor2 = value
Me.Invalidate()
End Set
End Property
Public Property UseHatchBrush() As Boolean
Get
Return drawhBrush
End Get
Set(ByVal value As Boolean)
drawhBrush = value
Me.Invalidate()
End Set
End Property
Public Property HatchColor() As Color
Get
Return HColor
End Get
Set(ByVal value As Color)
HColor = value
Me.Invalidate()
End Set
End Property
Public Property HatchStyle() As HatchStyle
Get
Return hStyle
End Get
Set(ByVal value As HatchStyle)
hStyle = value
Me.Invalidate()
End Set
End Property
Public Property UseGradient() As Boolean
Get
Return usegrad
End Get
Set(ByVal value As Boolean)
usegrad = value
Me.Invalidate()
End Set
End Property
Public Property DrawLabel() As Boolean
Get
Return drwLabel
End Get
Set(ByVal value As Boolean)
drwLabel = value
Me.Invalidate()
End Set
End Property
Public Property Draw3DBorder() As Boolean
Get
Return draw3D
End Get
Set(ByVal value As Boolean)
draw3D = value
Me.Invalidate()
End Set
End Property
Public Shadows Property BackColor() As Color
Get
Return MyBase.BackColor
End Get
Set(ByVal value As Color)
MyBase.BackColor = value
Me.Invalidate()
End Set
End Property
Private Sub Draw_3D_Border(ByVal g As Graphics)
Dim penWidth As Integer = Pens.White.Width
g.DrawLine(Pens.DarkGray, New Point(Me.ClientRectangle.Left, _
Me.ClientRectangle.Top), New Point(Me.ClientRectangle.Width - _
penWidth, Me.ClientRectangle.Top))
g.DrawLine(Pens.DarkGray, New Point(Me.ClientRectangle.Left, _
Me.ClientRectangle.Top), New Point(Me.ClientRectangle.Left, _
Me.ClientRectangle.Height - penWidth))
g.DrawLine(Pens.White, New Point(Me.ClientRectangle.Left, _
Me.ClientRectangle.Height - penWidth), New Point(Me.ClientRectangle.Width - _
penWidth, Me.ClientRectangle.Height - penWidth))
g.DrawLine(Pens.White, New Point(Me.ClientRectangle.Width -_
penWidth, Me.ClientRectangle.Top), New Point(Me.ClientRectangle.Width - _
penWidth, Me.ClientRectangle.Height - penWidth))
End Sub
Protected Overrides Sub OnResize(ByVal e As EventArgs)
Me.Invalidate() End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim g As Graphics = e.Graphics
Dim brush As SolidBrush = New SolidBrush(BarColor) Dim bkbrush As New SolidBrush(MyBase.BackColor) Dim hbrush As New HatchBrush(hStyle, _
HColor, Color.Transparent) Dim gbrush As LinearGradientBrush = New LinearGradientBrush_
(Me.ClientRectangle, Color.FromArgb(255, gradcolor1), _
Color.FromArgb(255, gradcolor2), LinearGradientMode.Vertical)
Dim percent As Decimal = (val - min) / (max - min) Dim cliRect As Rectangle = New Rectangle(0, 0, _
Me.ClientRectangle.Width, Me.ClientRectangle.Height) Dim rect As Rectangle = New Rectangle(1, 1, _
Me.ClientRectangle.Width - 2, Me.ClientRectangle.Height - 2) rect.Width = rect.Width * percent
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.AssumeLinear
If UseGradient = True Then
g.FillRectangle(bkbrush, cliRect) g.FillRectangle(gbrush, rect) If drawhBrush = True Then
g.FillRectangle(hbrush, rect) End If
End If
If UseGradient = False Then
g.FillRectangle(bkbrush, cliRect)
g.FillRectangle(brush, rect)
If drawhBrush = True Then
g.FillRectangle(hbrush, rect)
End If
End If
If draw3D = True Then
Draw_3D_Border(g) End If
If DrawLabel = True Then
Dim str As String = CType(val & "%", String) Dim mybrush As New SolidBrush(Me.ForeColor) g.DrawString(str, Me.Font, mybrush, _
New Point((Me.ClientRectangle.Width / 2) - str.Length * 4, _
(Me.ClientRectangle.Height / 2) - (FontHeight / 2))) End If
brush.Dispose()
bkbrush.Dispose()
hbrush.Dispose()
gbrush.Dispose()
g.Dispose()
End Sub
End Class
Some of the styles that can be achieved are as shown below:
ToDo
- Round corners (the code I had didn't work properly)
- Selectable region
- Animated Hatch Brush