TwinTimer class

A timer class that fires a Timer event at a repeating interval and reports the total elapsed time in milliseconds since the first event.

TwinTimer uses the Win32 SetTimer / KillTimer API directly and is not tied to any form or control. It can be instantiated in any module—standard modules, class modules, and form code alike—and the Timer event is raised on the thread that created the timer, through that thread’s Windows message pump, so no cross-thread marshalling is needed.

The elapsed-time counter passed to the Timer event is a monotonically increasing LongLong expressed in milliseconds. The implementation handles the 49.7-day rollover of the tick count that Windows supplies with each timer message (the same clock as GetTickCount), so the counter continues to increase correctly over long-running sessions.

Private WithEvents Timer1 As TwinTimer

Private Sub Form_Load()
    Set Timer1 = New TwinTimer
    Timer1.Interval = 1000   ' fire every second
End Sub

Private Sub Timer1_Timer(ByVal ElapsedTime As LongLong)
    Label1.Caption = "Elapsed: " & ElapsedTime & " ms"
End Sub

Properties

Enabled

Whether the timer fires Timer events. Boolean. Default: True.

Setting Enabled to False stops the Win32 timer and suppresses Timer events. Setting it back to True restarts the timer; the elapsed-time counter resets on the next tick.

Setting Enabled to True while Interval is 0 does not start the timer—the timer cannot run with a zero interval.

Syntax: object.Enabled [ = value ]

value
A Long; the property is read as a Boolean. Zero (False) suppresses events; any other value, such as True, allows them.

Note

Enabled defaults to True at construction. A freshly constructed TwinTimer with Interval = 0 (the initial default) does not fire until Interval is set to a positive value.

Interval

The number of milliseconds between successive Timer events. Long. Default: 0.

Setting Interval to a positive value restarts the underlying Win32 timer with the new period and resets the elapsed-time counter, provided Enabled is True. Setting it to 0 stops the timer without changing Enabled.

Syntax: object.Interval [ = milliseconds ]

milliseconds
A non-negative Long. A value of 0 stops the timer. A negative value raises run-time error 380 (Invalid property value).

Note

The Win32 SetTimer function raises an interval below 10 ms to 10 ms, and delivers its timer messages at the resolution of the system clock, typically 15–16 ms on standard Windows configurations. A short interval therefore does not give sub-15 ms accuracy.

Events

Timer

Raised each time the interval elapses.

Syntax: object_Timer ( ElapsedTime As LongLong )

ElapsedTime
A LongLong giving the total number of milliseconds since the first tick. On the very first tick after the timer starts (or restarts), ElapsedTime is 0. On each subsequent tick it reflects the cumulative milliseconds measured since that first tick.

The value is derived from the dwTime parameter supplied with WM_TIMER (the number of milliseconds since the system started, as GetTickCount returns it). The class accounts for the 49.7-day GetTickCount rollover so ElapsedTime continues to increase correctly without wrapping.

Private Sub Timer1_Timer(ByVal ElapsedTime As LongLong)
    ' ElapsedTime is 0 on the first tick, then increases by ~Interval each tick.
    Debug.Print "Tick at " & ElapsedTime & " ms"
End Sub

Example

This example creates a countdown that stops itself 10 seconds after the first tick.

Private WithEvents Countdown As TwinTimer

Private Sub Form_Load()
    Set Countdown = New TwinTimer
    Countdown.Interval = 500   ' check every 500 ms
End Sub

Private Sub Countdown_Timer(ByVal ElapsedTime As LongLong)
    Dim SecondsLeft As Long
    SecondsLeft = 10 - CLng(ElapsedTime \ 1000)
    If SecondsLeft <= 0 Then
        Countdown.Enabled = False
        Label1.Caption = "Done."
    Else
        Label1.Caption = "Stopping in " & SecondsLeft & " second(s)..."
    End If
End Sub

See Also