This code (Windows Forms) shows a series of timers so that the user can manually time a series of tasks. I decided to put this together today because next weekend I want to go through an activity (about 4-5 distinct tasks) and see how long it takes.

The main window is where all the action takes place.

The task buttons are a custom control (label, button, button, label) in a flow panel. The window expands as more tasks are added. The "Add Task" button asks for the task name before inserting a custom control in the panel.

All the time displays are updated based on a common timer. In addition, an individual time display is updated when that timer is stopped. For some slight added efficiency, the time displays are only updated when the timer is on - handlers are removed otherwise. Each timer is a 'one-off', there is no restarting or pausing - this is by design.

This works as I expected. If I were to create a more commercial product, then I would add some more features and probably double check any error handling/potential error conditions. I know that cancelling the input on entering a task will still give me a task (something that I would tidy up if I were going to share it) but it still works as intended (after all I don't have to start a timer if I don't want to!).

## Custom Control - individual task timer

Public Class ctlTaskTimer

Get
End Get
End Property

Public Sub UpdateTime()
End Sub

Private Sub btnTimerStart_Click(sender As Object, e As EventArgs) Handles btnTimerStart.Click
StartTimer()
End Sub

Private Sub btnTimerStop_Click(sender As Object, e As EventArgs) Handles btnTimerStop.Click
StopTimer()
End Sub

' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
btnTimerStop.Enabled = False
End Sub

Public Sub StartTimer()
btnTimerStart.Enabled = False
btnTimerStop.Enabled = True
End If
End Sub

Public Sub StopTimer()
btnTimerStart.Enabled = False ' single use control.
btnTimerStop.Enabled = False
UpdateTime()
End If
End Sub
End Class


## Main Window - the user application interface

Public Class TaskTimerMain

Event DoRefreshTime()
Private ptimer As New Windows.Forms.Timer()

Dim tName As String = InputBox("Enter a Name for the Task", "Task Entry", "<Name>")
End Sub

Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Application.Exit()
End Sub

Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
ptimer.Interval = (1 * 1000)  ' update every second
ptimer.Start()
End Sub

Private Sub timer_Tick(sender As Object, e As EventArgs)
RaiseEvent DoRefreshTime()
End Sub

Private Sub btnStartAll_Click(sender As Object, e As EventArgs) Handles btnStartAll.Click
For Each ctl As ctlTaskTimer In ctlTimerControls.Controls
ctl.StartTimer()
Next
End Sub

Private Sub btnStopAll_Click(sender As Object, e As EventArgs) Handles btnStopAll.Click
For Each ctl As ctlTaskTimer In ctlTimerControls.Controls
ctl.StopTimer()
Next
End Sub
End Class


I set this as a separate class rather than encapsulate it in the custom control. This separates the core data from the presentation and allows the task timer class to be re-used if I wanted.

Public Class TaskTimer

Private pName As String = "<Name>"
Private pTimeStart As DateTime = DateTime.Now
Private pTimeEnd As DateTime = DateTime.Now
Private pRunning As Boolean = False

Get
Return pName
End Get
End Property
Get
Return If(pRunning, DateTime.Now.Subtract(pTimeStart), pTimeEnd.Subtract(pTimeStart))
End Get
End Property
Get
Return pRunning
End Get
End Property

pRunning = False
End Sub

Sub StartTimer()
If Not Me.Running Then
pTimeStart = DateTime.Now
pRunning = True
End If
' ignore if try to start when already running
End Sub

Sub StopTimer()
If Me.Running Then
pTimeEnd = DateTime.Now
pRunning = False
End If
' ignore if try to stop when already stopped
End Sub
End Class

• I would suggest that rather than create a completely new Timer, you can inherit all the functionality that you have at the moment from the StopWatch class apart from the name which you can add yourself into your Timer class – David Wilson Jun 13 '18 at 11:18
• @DavidWilson: Did you want to turn that into an answer? This is code review, after all :-) – AJD Jun 13 '18 at 19:30
• @DavidWilson ... noting that it is not just the timer it self, but also the custom control. That I might extend it provides some context for a review (but of course, you cannot review non-existent code). – AJD Jun 13 '18 at 19:41