Create a progress bar for timer

Posted on 2014-11-14
Medium Priority
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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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 2000 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 (stackoverflow.com/a/9753302/884561, 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 86

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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses

764 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