04 Feb 2011
Creating a simple Stopwatch/Timer application with C# and Windows Forms
While working on a project today, I came across the need for a simple stopwatch/timer which would keep track of the total elapsed time until it was reset. It turned out to be a little trickier than I first assumed, so I've posted my code here for the convenience of anyone else who needs to do the same thing.
using System;
using System.Windows.Forms;
namespace StopwatchSpike
{
public partial class StopwatchSpikeForm : Form
{
// Because we have not specified a namespace, this
// will be a System.Windows.Forms.Timer instance
private Timer _timer;
private DateTime _startTime = DateTime.MinValue;
private TimeSpan _currentElapsedTime = TimeSpan.Zero;
private TimeSpan _totalElapsedTime = TimeSpan.Zero;
private bool _timerRunning = false;
public StopwatchSpikeForm()
{
InitializeComponent();
// Set up a timer and fire the Tick event every second (1000 ms)
_timer = new Timer();
_timer.Interval = 1000;
_timer.Tick += new EventHandler(_timer_Tick);
}
/// <summary>
/// Handle the Timer's Tick event
/// </summary>
/// <param name="sender">System.Windows.Forms.Timer instance</param>
/// <param name="e">EventArgs object</param>
void _timer_Tick(object sender, EventArgs e)
{
// We do this to 'chop off' any stray milliseconds
// resulting from the Timer's inherent inaccuracy,
// with the bonus that the TimeSpan.ToString() method
// will now show the correct HH:MM:SS format
var timeSinceStartTime = DateTime.Now - _startTime;
timeSinceStartTime = new TimeSpan(timeSinceStartTime.Hours,
timeSinceStartTime.Minutes,
timeSinceStartTime.Seconds);
// The current elapsed time is the time since the start button
// was clicked, plus the total time elapsed since the last reset
_currentElapsedTime = timeSinceStartTime + _totalElapsedTime;
// These are just two Label controls which display the current
// elapsed time and total elapsed time
_totalElapsedTimeDisplay.Text = _currentElapsedTime.ToString();
_currentElapsedTimeDisplay.Text = timeSinceStartTime.ToString();
}
/// <summary>
/// Handle Start/Stop button click
/// </summary>
/// <param name="sender">The Button control</param>
/// <param name="e">EventArgs object</param>
private void startButton_Click(object sender, EventArgs e)
{
// If the timer isn't already running
if (!_timerRunning)
{
// Set the start time to Now
_startTime = DateTime.Now;
// Store the total elapsed time so far
_totalElapsedTime = _currentElapsedTime;
_timer.Start();
_timerRunning = true;
}
else // If the timer is already running
{
_timer.Stop();
_timerRunning = false;
}
}
/// <summary>
/// Handle Reset button click
/// </summary>
/// <param name="sender">The Button control</param>
/// <param name="e">EventArgs object</param>
private void resetButton_Click(object sender, EventArgs e)
{
// Stop and reset the timer if it was running
_timer.Stop();
_timerRunning = false;
// Reset the elapsed time TimeSpan objects
_totalElapsedTime = TimeSpan.Zero;
_currentElapsedTime = TimeSpan.Zero;
}
}
}
Because I wasn't interested in sub-second accuracy, I've used System.Windows.Forms.Timer
for simplicity, but the principle is the same whichever timer class you use.
If you want to find out more about the differences between System.Threading.Timer
, System.Windows.Forms.Timer
and System.Timers.Timer
, it's definitely worth reading this article comparing the Timer classes in the .NET Framework class library.
You can view the full source here and download a complete working VS2010 Solution here.
Questions or comments? Get in touch @markeebee, or email [Turn On Javascript To View Email Address].
More articles
© Mark Ashley Bell 2023