Purin Purin - 3 days ago 5
Vb.net Question

How do I subtract time from a running countdown timer?

Basically, I have a timer that counts down from 3 minutes while the user takes a test. If the user skips a question, I want to incur a 15-second penalty. So they then have 15 seconds less time to finish. Example: The Timer is at 2:35. The user hits skip, and the timer goes down to 2:20, and continues on. Here is my code:

Public Class Form1
Private TargetDT As DateTime
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.AcceptButton = btnprocess
End Sub
Private Sub tmrCountdown_Tick(sender As Object, e As System.EventArgs) Handles tmrCountdown.Tick
Dim ts As TimeSpan = TargetDT.Subtract(DateTime.Now)
If ts.TotalMilliseconds > 0 Then
lbltimer.Text = ts.ToString("mm\:ss")
Else
lbltimer.Text = "00:00"
tmrCountdown.Stop()
MessageBox.Show("Done")
End If
End Sub

Private Sub btnskip_Click(sender As Object, e As EventArgs) Handles btnskip.Click
' This is where I want to subtract 15 seconds
Dim ts As TimeSpan = TargetDT.Subtract(DateTime.Now.Add(TimeSpan.FromSeconds(15)))
End Sub

Private Sub btnbegin_Click(sender As Object, e As EventArgs) Handles btnbegin.Click
tmrCountdown.Interval = 1
TargetDT = DateTime.Now.Add(TimeSpan.FromMinutes(2.5))
tmrCountdown.Start()
End Sub
End Class

Dai Dai
Answer

Just change your TargetDT value, so on the next Tick event the display will be updated.

I also changed your code to use DateTime.UtcNow instead of DateTime.Now so clever users can't change the timezone to gain additional time (as changing the timezone does not require administrative/elevated permissions).

You also don't need to specify a super-high timer frequency (you had it set to update every milisecond). This is excessive. I set it to 4Hz so the on-screen display won't lag too much.

Private Sub btnskip_Click(sender As Object, e As EventArgs) Handles btnskip.Click

    Me.TargetDT = Me.TargetDT.Subtract( TimeSpan.FromSeconds( 15 ) )

End Sub

Private Sub tmrCountdown_Tick(sender As Object, e As System.EventArgs) Handles tmrCountdown.Tick

    Dim now As DateTime = DateTime.UtcNow

    If now > Me.TargetDT Then

        Me.lbltimer.Text = "00:00"
        Me.tmrCountdown.Stop()
        MessageBox.Show("Done")

    Else

        Dim diff As TimeSpan = Me.TargetDT - now
        Me.lbltimer.Text = diff.ToString("mm\:ss")

    End If

End Sub

Private Sub btnbegin_Click(sender As Object, e As EventArgs) Handles btnbegin.Click

    Me.tmrCountdown.Interval = 250 ' no need to update more than 4 times a second
    Me.TargetDT = DateTime.UtcNow.Add( TimeSpan.FromMinutes(2.5) )

    Me.tmrCountdown.Start()
End Sub
Comments