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
The format should be displayed, for example for one hour, 12 minutes, 23 seconds as 01:12:23
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.
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
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
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
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
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
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
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
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
ASKER
Adjusted points to 55
use whatever code worked before but make the timer interval 50.
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
Rick
ASKER
Adjusted points to 75
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?
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
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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.
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