I have a project that I have to do a Stopwatch. It works but it's not accurate compared to the Windows Timer. Also, I want to know if there is another efficient and simple way to do it, if so, how can I do it?. The interval of the Timer is 1.
Here's my code:
Dim min As Integer = 30
Dim seg As Integer = 59
Dim mseg As Integer = 99
Private Sub tmTimer_Tick(sender As Object, e As EventArgs) Handles tmTimer.Tick
If lblStopWatch.Text = "00:00:00" Then
lblStopWatch.ForeColor = Color.DarkGray
tmTimer.Enabled = False
min = 30
seg = 59
mseg = 99
Else
mseg -= 1
If mseg < 0 Then
mseg = 99
seg -= 1
If seg < 0 Then
seg = 59
min -= 1
End If
End If
If min < 10 And seg < 10 And mseg < 10 Then
lblStopWatch.Text = "0" + min.ToString + ":0" + seg.ToString + ":0" + mseg.ToString
ElseIf min < 10 And seg < 10 Then
lblStopWatch.Text = "0" + min.ToString + ":0" + seg.ToString + ":" + mseg.ToString
ElseIf min < 10 And mseg < 10 Then
lblStopWatch.Text = "0" + min.ToString + ":" + seg.ToString + ":0" + mseg.ToString
ElseIf seg < 10 And mseg < 10 Then
lblStopWatch.Text = min.ToString + ":0" + seg.ToString + ":0" + mseg.ToString
Else
If mseg < 10 Then
lblStopWatch.Text = min.ToString + ":" + seg.ToString + ":0" + mseg.ToString
ElseIf seg < 10 Then
lblStopWatch.Text = min.ToString + ":0" + seg.ToString + ":" + mseg.ToString
ElseIf min < 10 Then
lblStopWatch.Text = "0" + min.ToString + ":" + seg.ToString + ":" + mseg.ToString
Else
lblStopWatch.Text = min.ToString + ":" + seg.ToString + ":" + mseg.ToString
End If
End If
End If
End Sub
And here's the Button that can start the Timer:
Private Sub btnAcept_Click(sender As Object, e As EventArgs) Handles btnAcept.Click
lblCronometro.ForeColor = Color.RoyalBlue
lblCronometro.Text = "30:00:00"
tmCronometro.Enabled = True
tmCronometro.Start()
End Sub
If the example is in C# or vb, I can get both. Thanks.
HINTS
If you want to do it yourself instead of using the existing StopWatch
class, another option would be to keep track of the time that the stopwatch started (start
) and how long the stopwatch has been running (elapsed
).
With the start
value, we can calculate the elapsed
time in the timer's Tick
event like:
// elapsed is a TimeSpan object
elapsed = DateTime.Now - start;
If we add the ability to stop the stopwatch and then start it again (without resetting it), then we have to take that "downtime" into consideration. We can do this in our Start
button click event by subtracting the elapsed
time from the current time and using that value as the start time:
// start is a DateTime object
start = DateTime.Now.Subtract(elapsed);
Then, when we want to display the elapsed time to the user, we can just use our elapsed
field and format it like: hours:minutes:seconds.milliseconds
using a custom format string.
// I noticed you're doing a countdown timer, so we want to display the difference
// between the original duration of 30 minutes and the elapsed time we've been running
lblStopwatch.Text = (duration - elapsed).ToString("hh\\:mm\\:ss\\.ff");
ANSWER
If those hints aren't enough, here's a sample project using that strategy:
public partial class Form1 : Form
{
private DateTime _startTime;
private TimeSpan _elapsedTime;
// The starting duration for the countdown timer
private readonly TimeSpan _duration = TimeSpan.FromMinutes(30);
public Form1()
{
InitializeComponent();
ResetTimer();
}
private void ResetTimer()
{
_startTime = DateTime.Now;
_elapsedTime = TimeSpan.Zero;
UpdateStopwatchDisplay();
}
private void UpdateStopwatchDisplay()
{
// Display the current duration to the user
lblStopwatch.ForeColor = timer1.Enabled ? Color.RoyalBlue : Color.DarkGray;
lblStopwatch.Text = (_duration - _elapsedTime).ToString("hh\\:mm\\:ss\\.ff");
}
private void btnStart_Click(object sender, EventArgs e)
{
// Subtract 'elapsed' from 'now' to account for any stoppage time
_startTime = DateTime.Now.Subtract(_elapsedTime);
UpdateStopwatchDisplay();
timer1.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
timer1.Stop();
UpdateStopwatchDisplay();
}
private void btnReset_Click(object sender, EventArgs e)
{
ResetTimer();
}
private void timer1_Tick(object sender, EventArgs e)
{
// Update elapsed time
_elapsedTime = DateTime.Now.Subtract(_startTime);
// Stop the timer if we've reached our duration
if (_elapsedTime >= _duration)
{
_elapsedTime = _duration;
timer1.Stop();
}
UpdateStopwatchDisplay();
}
}