Create a progress bar for timer

Posted on 2014-11-14
Last Modified: 2014-12-17
Hi EE,

In VB.NET, I would like to have on my form a progress bar that decreases.
Lets say I tell the form that the timer is 4 minutes.. I would like the progress abr to decreases to zero at 4mins and it would start Green and going yellow up to red once the timer reaches lets say 3mins or 1/3 left...

can you help me ?

Either a bar or a kind of circle like a clock with a line going clockwise
Question by:PhilippeRenaud
LVL 44

Expert Comment

ID: 40442884
There is a ProgressBar control - put one onto your form.

Have a look at the following:

Set the max and minimum values to 240 and 0 (seconds in 4 minutes, try a step of -1 to decrement) then do the PerformStep in your timer event - I assume you wanted a step per second with the above values.
LVL 75

Accepted Solution

käµfm³d   👽 earned 500 total points
ID: 40443138
I try to avoid referencing other forums if I can help it, but there is a very neat solution on SO (, by user1032613) that does exactly what you are seeking--at least in terms of the colors. Adapting the code to VB and combining it with what Andy mentioned, you could have something like:

Imports System.Runtime.InteropServices

Public Class Form1
    Private Const RED As Integer = 2
    Private Const YELLOW As Integer = 3
    Private Const GREEN As Integer = 1

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
    Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal w As IntPtr, ByVal l As IntPtr) As IntPtr
    End Function

    Public Sub SetState(ByVal pBar As ProgressBar, ByVal state As Integer)
        SendMessage(pBar.Handle, 1040, New IntPtr(state), IntPtr.Zero)
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim currentPercentage As Double


        currentPercentage = (Me.ProgressBar1.Value / Me.ProgressBar1.Maximum)

        If currentPercentage < 0.25 Then
            SetState(Me.ProgressBar1, RED)
        ElseIf currentPercentage < 0.75 Then
            SetState(Me.ProgressBar1, YELLOW)
        ElseIf currentPercentage <= 0 Then
            Me.Timer1.Enabled = False
        End If

    End Sub
End Class

Open in new window

To yield:

LVL 85

Expert Comment

by:Mike Tomlinson
ID: 40443225
This is pared down and modified code from my "Kids Alarm Clock" project, which I demonstrate here:
Full Source Code:

Obviously this doesn't do exactly what you described, but I thought you might be interested in the parts of the code that draw the circular portions.  They represent how much time is left until the alarm goes off.  The outer red band is how many hours are left.  The middle blue band is how many minutes is left.  The inner green band is how many seconds are left.  In this image, there is 5 hours, 36 minutes, and 15 seconds left:
5 hours, 36 minutes, 15 seconds left
CircularCountdownTimer UserControl:
Public Class CircularCountdownTimer

    Private Const OuterHourDistance As Double = 0.98
    Private Const InnerHourDistance As Double = 0.78

    Private Const OuterMinuteDistance As Double = 0.68
    Private Const InnerMinuteDistance As Double = 0.48

    Private Const OuterSecondDistance As Double = 0.38
    Private Const InnerSecondDistance As Double = 0.18

    ' The Target Time to stop at:
    Private _StopHour As Integer ' 0 to 23
    Private _StopMinute As Integer ' 0 to 59
    Private _StopSecond As Integer ' ' 0 to 59

    Private ReadOnly Property Time() As TimeSpan
            Return New TimeSpan(Me._StopHour, Me._StopMinute, Me._StopSecond)
        End Get
    End Property

    Public Sub SetDuration(ByVal TS As TimeSpan)
        Dim StopTime As DateTime = DateTime.Now.Add(TS)
        _StopHour = StopTime.TimeOfDay.Hours
        _StopMinute = StopTime.TimeOfDay.Minutes
        _StopSecond = StopTime.TimeOfDay.Seconds
    End Sub

    Private WithEvents Tmr As System.Windows.Forms.Timer

    Private Sub CircularCountdownTimer_Load(sender As Object, e As EventArgs) Handles Me.Load
        ' Double Buffered to reduce flicker
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.SetStyle(ControlStyles.DoubleBuffer, True)
        Me.SetStyle(ControlStyles.ResizeRedraw, True)

        Tmr = New System.Windows.Forms.Timer
        Tmr.Interval = 1000
        Tmr.Enabled = True
    End Sub

    Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
    End Sub

    Private Sub CircularCountdownTimer_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    End Sub

    Private Sub CircularCountdownTimer_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim C As Color
        Dim cx As Single = Me.Width / 2
        Dim cy As Single = Me.Height / 2
        Dim SmallerDimension = Math.Min(Me.Width, Me.Height)
        Dim innerDistance, outerDistance As Single

        Static hourList As New List(Of Point)
        Static prevHour As Integer = -1
        Static minList As New List(Of Point)
        Static prevMin As Integer = -1
        Static secList As New List(Of Point)
        Static prevSec As Integer = -1

        Dim ts As TimeSpan = Me.CalcKillTime.Subtract(DateTime.Now)
        Dim startAngle As Integer = GetHourAngle(12)
        Dim stopAngle As Integer
        Dim ps() As Point

        If ts.Hours >= 1 Then
            C = Color.Red
            stopAngle = GetMinuteAngle(ts.Hours * 5)
            If stopAngle <> prevHour Then
                outerDistance = SmallerDimension * OuterHourDistance / 2
                innerDistance = SmallerDimension * InnerHourDistance / 2
                BuildTimeSlice(hourList, cx, cy, stopAngle, innerDistance, outerDistance)
                prevHour = stopAngle
            End If
            ps = hourList.ToArray
            Using hb As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.Percent10, Color.Black, C)
                e.Graphics.FillPolygon(hb, ps)
            End Using
            e.Graphics.DrawLines(Pens.Black, ps)
        End If
        If ts.Minutes > 0 Then
            C = Color.Blue
            stopAngle = GetMinuteAngle(ts.Minutes)
            If stopAngle <> prevMin Then
                outerDistance = SmallerDimension * OuterMinuteDistance / 2
                innerDistance = SmallerDimension * InnerMinuteDistance / 2
                BuildTimeSlice(minList, cx, cy, stopAngle, innerDistance, outerDistance)
                prevHour = stopAngle
            End If
            ps = minList.ToArray
            Using hb As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.Percent10, Color.Black, C)
                e.Graphics.FillPolygon(hb, ps)
            End Using
            e.Graphics.DrawLines(Pens.Black, ps)
        End If
        If ts.Seconds > 0 Then
            C = Color.LightGreen
            stopAngle = GetMinuteAngle(ts.Seconds)
            If stopAngle <> prevMin Then
                outerDistance = SmallerDimension * OuterSecondDistance / 2
                innerDistance = SmallerDimension * InnerSecondDistance / 2
                BuildTimeSlice(secList, cx, cy, stopAngle, innerDistance, outerDistance)
                prevHour = stopAngle
            End If
            ps = secList.ToArray
            Using hb As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.Percent10, Color.Black, C)
                e.Graphics.FillPolygon(hb, ps)
            End Using
            e.Graphics.DrawLines(Pens.Black, ps)
        End If
    End Sub

    Private Sub BuildTimeSlice(ByVal pList As List(Of Point), _
                               ByVal cx As Single, ByVal cy As Single, ByVal MinuteAngle As Integer, _
                               ByVal innerDistance As Single, ByVal outerDistance As Single)
        pList.Add(GetPoint(cx, cy, 360, outerDistance))
        For i As Integer = 360 To MinuteAngle Step -6
            pList.Add(GetPoint(cx, cy, i, outerDistance))
            If i Mod 30 = 0 Then
                pList.Add(GetPoint(cx, cy, i, innerDistance))
                pList.Add(GetPoint(cx, cy, i, outerDistance))
            End If
        pList.Add(GetPoint(cx, cy, MinuteAngle, innerDistance))
        For i As Integer = MinuteAngle To 360 Step 6
            pList.Add(GetPoint(cx, cy, i, innerDistance))
        pList.Add(GetPoint(cx, cy, 360, outerDistance))
    End Sub

    Private Function GetHourAngle(ByVal hour As Integer) As Integer
        hour = IIf(hour = 0, 12, IIf(hour <= 12, hour, hour - 12))
        Return (-hour + 12) * 30
    End Function

    Private Function GetMinuteAngle(ByVal minute As Integer) As Integer
        Return -6 * (minute - 60)
    End Function

    Private Function GetPoint(ByVal cx As Single, ByVal cy As Single, ByVal angleInDegrees As Single, ByVal distance As Single) As Point
        ' angleInDegrees
        ' Valid values are 0 --> 359 (six degrees = one minute on clock)
        ' draw a line from the center of the circle:
        ' 0 = up
        ' 90 = left
        ' 180 = down
        ' 270 = right

        ' Offset and Invert Angle then Convert Degrees to Radians
        angleInDegrees = -(angleInDegrees + 90) * Math.PI / 180

        ' Compute the point that is at the specified angle from horizontal and at the specifed distance
        Return New Point(cx + distance * Math.Cos(angleInDegrees), cy + distance * Math.Sin(angleInDegrees))
    End Function

    Public Function CalcKillTime() As DateTime
        Dim AM As Boolean = DateTime.Now.Hour < 12
        Dim ts As TimeSpan = Me.Time
        If AM Then
            If DateTime.Now.Hour = 0 AndAlso Me.Time.Hours = 12 Then
                If DateTime.Now.Minute < ts.Minutes Then
                    Return DateTime.Today.AddMinutes(ts.Minutes)
                End If
            ElseIf ts < DateTime.Now.TimeOfDay Then
                ts = ts.Add(New TimeSpan(12, 0, 0))
            End If
            Return DateTime.Today.Add(ts)
            If ts.Hours = 12 Then
                If DateTime.Now.Hour = 12 Then
                    If ts > DateTime.Now.TimeOfDay Then
                        Return DateTime.Today.Add(ts)
                    End If
                End If
                Return DateTime.Today.AddDays(1).AddMinutes(ts.Minutes)
                ts = New TimeSpan(ts.Hours + 12, ts.Minutes, 0)
                If ts > DateTime.Now.TimeOfDay Then
                    Return DateTime.Today.Add(ts)
                    Return DateTime.Today.AddDays(1).Add(New TimeSpan(ts.Hours - 12, ts.Minutes, 0))
                End If
            End If
        End If
    End Function

End Class

Open in new window


Author Closing Comment

ID: 40504919
Hi sorry for the long wait,
Thanks this is perfect

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
compare between entities in entity framework 8 72
VB.Net - KeyPress Event 4 36
Please explain the parts of these 2 LINQ expressions 3 30
.NET 2008 VB and C# 6 27
In my previous article ( we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question