Multiple timers

J

John Crawford

I implemented a clock in my presentation. It is a 1 second timer, and
displays the time. However some of the slides display a userform that
has a .1 second timer. I use the SetTimer and KillTimer functions, and
if I have only one of the timers running it works ok. If, however, booth
timers are running it seems to confuse the timer, and I cannot stop it.
The functions use the window handle (hwnd). In the example that I am
using hwnd = 0. Could this be what is confusing the timers? and if so,
how do I find the handle for the slide and the userform?
Any help would be appreciated.
Thanks
John Crawford.
 
D

David Marcovitz

I think this depends on the specific code. Perhaps, you could post what you
have, and someone can look at that. Most of the timer functions that I have
seen have some kind of a global variable keeping track of when the timer was
started. I would imagine that using such code with two timers would cause
the two timers to both try to write to the same variable and interfere with
each other. But without seeing your code, I could imagine that it is also
something entirely different.
--David
--
David M. Marcovitz
Author of _Powerful PowerPoint for Educators_
http://www.PowerfulPowerPoint.com/
Microsoft PowerPoint MVP
Associate Professor, Loyola University Maryland
 
J

John Crawford

You are right. I thought that there might have been something, like you
cannot have two timers. Here is the code.

Module 1 is the one that controls the .1 second timer:

'========================================================================
Option Explicit
Public Cages(12, 5) As Integer
'API Declarations
Declare Function SetTimer Lib "user32" _
(ByVal hwnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As
Long) As Long

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

' Public Variables
Public ID As Long 'Id of the timer
Public tSeconds As Single 'Number of seconds for the timer to count
Public TmrEnabled As Boolean 'Timer has been created
Public SlideNo As Integer
Public SlideName As String


Function TimerStartStop() As Boolean
'Turn the timer on/off
Dim rc As Boolean 'Return code

rc = True 'Initialize the return code

'If the timer is stopped then start it
If Not TmrEnabled Then
'Start the timer
'tSeconds = 2 'Determine the timer rate in seconds

'Start the timer (timer counts in miliseconds)
ID = SetTimer(0, 0, tSeconds * 1000, AddressOf Timer)
MsgBox "Set ID=" & ID

'Error in starting timer
If ID = 0 Then
MsgBox "Unable to create the timer", vbCritical + vbOKOnly, "Error"
rc = False
Else

TmrEnabled = True 'Set timer started flag
End If

Else
'Stop the timer
ID = KillTimer(0, ID) 'Stop this timer
MsgBox "Kill ID=" & ID

'Not successful
If ID = 0 Then
MsgBox "Unable to stop the timer", vbCritical + vbOKOnly, "Error"
rc = False
End If

TmrEnabled = False 'Reset state
End If

TimerStartStop = rc 'Return status
End Function

Sub Timer(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal idEvent As Long, ByVal dwTime As Long)
If frmMouse1.Page = 5 Then
frmMouse1.lblDblClick.Visible = False

TimerStartStop
End If

If frmMouse1.Page = 4 Or frmMouse1.Page = 6 Or frmMouse1.Page = 7 Then
frmMouse1.lbltime.Caption = Val(frmMouse1.lbltime.Caption) + 0.1 &
" sec."
End If
End Sub
'=========================================================================

The second module controls the display of the time.
'===========================================================================
Option Explicit

' Public Variables
Public ID2 As Long 'Id of the timer
Public tSeconds2 As Integer 'Number of seconds for the timer to count
Public Enabled2 As Boolean 'Timer has been created
Public SlideNo2 'The slide number
Public currentSlide As Slide 'The slide

Function Timer2StartStop() As Boolean
'Turn the timer on/off
Dim rc As Boolean 'Return code

rc = True 'Initialize the return code

'If the timer is stopped then start it
If Not Enabled2 Then
'Start the timer
tSeconds2 = 1 'Determine the timer rate in seconds

'Start the timer (timer counts in miliseconds)
ID2 = SetTimer(0, 0, tSeconds2 * 1000, AddressOf Timer2)
MsgBox "Set ID2=" & ID2 'Added to check the id when created

'Error in starting timer
If ID2 = 0 Then
MsgBox "Unable to create the timer", vbCritical + vbOKOnly, "Error"
rc = False
Else
'Show time
SlideNo2 = SlideShowWindows(1).View.Slide.SlideIndex 'Get the
slide number
Set currentSlide = ActivePresentation.Slides(SlideNo2) 'Get the
slide

'Display the time on the current slide
currentSlide.Shapes("btnClock").OLEFormat.Object.Caption = Time
'Update the time

Enabled2 = True 'Set timer started flag
End If

Else
'Stop the timer
ID2 = KillTimer(0, ID2) 'Stop this timer
MsgBox "Kill ID2=" & ID2 'Added to show when the timer stops
'Not successful
If ID2 = 0 Then
MsgBox "Unable to stop the timer", vbCritical + vbOKOnly, "Error"
rc = False
End If

Enabled2 = False 'Reset state
End If

Timer2StartStop = rc 'Return status
End Function

Sub Timer2(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal idEvent As Long, ByVal dwTime As Long)
Dim rc As Boolean
On Error GoTo badone
'This is the OnTimer VB event
'Once the timer has been created, this subroutine will be called
'each time the timer time elapses

SlideNo2 = SlideShowWindows(1).View.Slide.SlideIndex 'Get the slide
number
Set currentSlide = ActivePresentation.Slides(SlideNo2) 'Get the slide

'Display the time on the current slide
currentSlide.Shapes("btnClock").OLEFormat.Object.Caption = Time
'Update the time

Exit Sub
badone:
'When the presentation ends it triggers an error.
'This will just stop the timer
rc = Timer2StartStop()
End Sub

'===========================================================================
I have made the names unique for each timer.
It seems that the Timer2 is being triggered multiple times, but the
msgbox does not show these events.
If anyone wishes I will send the entire presentation, however I think
the problem is here.
Again, thanks
John Crawford
 
B

Bill Dilworth

You might consider a slightly different approach.

Use the 'timer' as the interrupt to update the display of any active timers,
and only kill it when there are no active displays. It only takes a little
math to keep the time in Private variables.

Just my 0.02

Bill Dilworth
 
J

John Crawford

Thanks for your comment. The clock display was added, and I was hoping
to not have to make drastic changes to handle both. I had been thinking
of something along the lines of you suggestion. There are some
complications. The .1 second timer is used to time games. So it must
only count during the game. Also, the 1 second timer may or may not be
used, depending on the instructor. None of these problems are impossible
to solve, it will just require more controls.
John
 
J

John Crawford

I think that I have found the problem. It really had nothing to do with
the timers. When I recoded it, as per Bill's comment. I noticed that
when the userform closed that the clock timer stopped. It was NOT being
stopped through the normal routine. I looked at the userform, and it
uses the End command to terminate the userform. I tried userform.Hide,
and the problem went away. I would have thought that the scope of the
End command would have been just within the module, but it appears that
it is wider.
John
 
B

Bill Dilworth

It has been my experience that the END command should never be used in VBA
unless you are very, very serious. It does tend to exceed its authority on
a regular basis, often causing all VBA to stop instead of just the
subroutine you are in.

I'm glad you found the solution.

Bill Dilworth
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top