Link to home
Start Free TrialLog in
Avatar of zrick
zrick

asked on

Displaying Stopwatch on Label

I need to create a stopwatch that will show the time elapsing (not elapsed) in a label.caption. The resolution must be accurate to the half-second.

The format should be displayed, for example for one hour, 12 minutes, 23 seconds as 01:12:23
Avatar of bear454
bear454

Implement a timer control, set a perscribed interval, in this a half second, and in the timer event of the timer control, increment a variable by the time increment of the timer, and spit it our with formats & and a little math, as follows:

Public Runtime as double

Private Sub tmrStats_Timer()
    Runtime = Runtime + .5
    lblRuntime.Caption = "Elapsed time: " & Format((Runtime \ 3600), "00") & ":" & Format(((Runtime Mod 3600) \ 60), "00") & ":" & Format((Runtime Mod 60), "00.0")
End Sub

Avatar of zrick

ASKER

The code you provided works, but I need a more accurate timekeeper.
The stopwatch code runs quickly for two seconds then slows for two, then quick for two, etc...., Over a minute it is not accurate compared to the system clock. What I really need is for the system clock to be as closely matched as possible. When I begin the stopwatch, it should be like setting the systemtime back to midnight 00:00:00, each second of the system clock should advance the stopwatch by a second.

The reason this is important is that I am collecting physiologic data that is referenced to the system clock. I need to display the actual system clock (which is easy) and the time elapsed from when I begin recording. The time elapsed is calculated by the physiologic program based on the system clock, but it is not displayed on screen where I need it.
Try this.. the timer event itself takes like 22ms or some such
but this works pretty good:
(its for hours mins and seconds.but Ithink it could be changed for your needs)

Private Sub Timer1_Timer()
diffTime = DateDiff("s", xtime, Now)
mytime = CInt(diffTime \ 600) & ":" & CInt(diffTime \ 60) & ":" & CInt(diffTime Mod 60)
timervalue.Caption = Format(mytime, "hh:mm:ss")
End Sub

You can also go here:
www.leahcim.com
click on VB
and there is a timer example using
API
Avatar of zrick

ASKER

myqlg, I tried both your examples. The first code gave me a runtime error 6 (overflow). When I went into Debug, this occured on the line mytime = ... I use VB 6.0, could that account for that? The api code from www.leahcim.com ran fine but was inaccurate compared to the system clock. When running it loses 6 seconds each minute compared with the system clock (I ran this both compiled and not compiled). I really need the time accurate to the system clock. Any ideas about that overflow error?
The key is to crunch the math of the date data type. left of the decimal is the number of days, to the right is the time. For example 1/24 or ~0.04166666667 is 1 hour, or 1/86400 or ~0.00001157407 is 1 second.

Public StartTime as date
Timer1.interval = 250 'run every quarter-second

Timer1_Timer()
    Label1.Caption = Format(((Now - StartTime) \(1/24)),"00") & _
      ":" & Format(((Now - Starttime) \ (1/1440)),"00" & _
      ":" & Fomtat(((Now-Starttime) \(1/86400)),"00"
End Sub

Avatar of zrick

ASKER

Bear have you tried that code you sent me using the date? I can't get it to work. Divide by zero errors. I tried also with out dividing by the reciprocal, but that doesn't work well either. I need the counter to be continually updating like a stopwatch, this code doesn't seem to do that. Did it work for you?
Sorry zrick - I wrote it off the top of my head.  Here's a working copy - save it as Stopwatch.frm I'm also submitting as an answer for "monitoring keystrokes...", just watch the keyboard buffer instead of a start button.

VERSION 5.00
Begin VB.Form Form1
   Caption         =   "StopWatch"
   ClientHeight    =   1110
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   4470
   LinkTopic       =   "Form1"
   ScaleHeight     =   1110
   ScaleWidth      =   4470
   StartUpPosition =   3  'Windows Default
   Begin VB.CommandButton Command2
      Caption         =   "Stop"
      Height          =   495
      Left            =   3840
      TabIndex        =   7
      Top             =   600
      Width           =   615
   End
   Begin VB.CommandButton Command1
      Caption         =   "Start"
      Height          =   495
      Left            =   3840
      TabIndex        =   3
      Top             =   120
      Width           =   615
   End
   Begin VB.Timer Timer1
      Interval        =   250
      Left            =   4080
      Top             =   0
   End
   Begin VB.Label Label6
      Alignment       =   1  'Right Justify
      BorderStyle     =   1  'Fixed Single
      Caption         =   "Elapsed"
      Height          =   255
      Left            =   0
      TabIndex        =   6
      Top             =   840
      Width           =   735
   End
   Begin VB.Label Label5
      Alignment       =   1  'Right Justify
      BorderStyle     =   1  'Fixed Single
      Caption         =   "Now"
      Height          =   255
      Left            =   0
      TabIndex        =   5
      Top             =   480
      Width           =   735
   End
   Begin VB.Label Label4
      Alignment       =   1  'Right Justify
      BorderStyle     =   1  'Fixed Single
      Caption         =   "Start"
      Height          =   255
      Left            =   0
      TabIndex        =   4
      Top             =   120
      Width           =   735
   End
   Begin VB.Label Label3
      BorderStyle     =   1  'Fixed Single
      Caption         =   "hh:mm:ss"
      Height          =   255
      Left            =   840
      TabIndex        =   2
      Top             =   840
      Width           =   2895
   End
   Begin VB.Label Label2
      BorderStyle     =   1  'Fixed Single
      Caption         =   "hh:mm:ss"
      Height          =   255
      Left            =   840
      TabIndex        =   1
      Top             =   480
      Width           =   2895
   End
   Begin VB.Label Label1
      BorderStyle     =   1  'Fixed Single
      Caption         =   "hh:mm:ss"
      Height          =   255
      Left            =   840
      TabIndex        =   0
      Top             =   120
      Width           =   2895
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Run As Boolean
Private StartTime As Date

Private Sub Command1_Click()
    StartTime = Now
    Run = True
    Label1.Caption = Format(Now, "hh:mm:ss")
End Sub

Private Sub Command2_Click()
    Run = False
End Sub

Private Sub Timer1_Timer()
    Label2.Caption = Format(Now, "hh:mm:ss")
    If Run Then
        Label3.Caption = Format(((Now - StartTime) / (1 / 24)), "00") & _
          ":" & Format(((Now - StartTime) / (1 / 1440)), "00") & _
          ":" & Format(((Now - StartTime) / (1 / 86400)), "00")
    End If
End Sub

Avatar of zrick

ASKER

Bear, It is getting much closer. The second intervals are directly parallel to the seconds of the system clock (of course - good thinking), however, the stopwatch seems to think that there are 30 seconds in the first minute, and the second minute comes around 1 minute 90 seconds (as displayed), then the seconds start being displayed in the hundreds. 00:03:116 (something like that indicating 3 minutes and 116 seconds)

Also, VB-6 did not understand how to interpret these lines, but it ran okay with them rem-ed out

Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

VB6 also didn't like the Begin statements, such as
Begin VB.Label Label3
But it accepted the values fine when I entered them manually into the Properties box


Avatar of zrick

ASKER

Adjusted points to 55
use whatever code worked before but make the timer interval 50.
Avatar of zrick

ASKER

Edunc, setting the interval to 50 does not correct the problem. Were you responding to the 1/2 second part of this question, then it would be 500. The question that was raised was about trying to get bear's code working. At 30 seconds, his code which is actually quite elegant otherwise, registers  1 minute (see my reply to bear).
Rick
Avatar of zrick

ASKER

Adjusted points to 75
Avatar of zrick

ASKER

On the code provided by Bear, the stopwatch seems to think that there are 30 seconds in the first minute, and the second minute comes around 1 minute 90 seconds (as displayed), then the seconds start being displayed in the hundreds. 00:03:116 (something like that indicating 3 minutes and 116 seconds)  

Anybody know how to fix this?
You might try something real simple like
Simply call SetAlarm (should pass the control and set it to a private member) to start the timer and EndTimer to end the timer...

Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Private Timer As Long
Sub SetAlarm()
    Timer = SetTimer(0, 0, 1000, AddressOf TimerProc)
End Sub
Sub EndAlarm()
    KillTimer Timer
End Sub
Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
Static Ticks As Long
Dim Hours As Long, Minutes As Long, Seconds As Long
Ticks = Ticks + 1
Seconds = Ticks Mod 60
Minutes = Ticks \ 60
Hours = Minutes \ 60
Minutes = Minutes Mod 60

Form1.Label1.Caption = Format(Hours, "00") & ":" & Format(Minutes, "00") & ":" & Format(Seconds, "00")
End Sub

My block copy dint pick up the Declaration for SetTimer.... sorry

Declare Function SetTimer Lib "user32" Alias "SetTimer" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long

Also the call to the KillTimer should be KillTimer 0, Timer... sorry again...
This is starting to piss me off. You better accept my next answer. ={
ASKER CERTIFIED SOLUTION
Avatar of bear454
bear454

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of zrick

ASKER

Bear, You're latest code worked well. I ran the compiled version for 2 hours without a problem. Thank you for taking the time to work on this code until it performed without errors. I increased the points to 105, which is the full amount I have available, and of course I gave you a well deserved "A."

My next step is to see if I can trigger this stopwatch when I begin the physiological recording in another program. I am going see if the stopwatch program can monitor for the next mouse click occuring in another program and then begin the timer.