This lesson
describes the timer control. Unlike most other controls, the user never sees the timer control, even though you place the timer control on the form just as you place other controls on the form. The timer control keeps track of passing time
intervals, and
automatically triggers its own events when a preset time period goes by.
Unlike the other controls that respond to events, the timer control both triggers events and responds to events through the event procedures that you write. The timer
control's property settings determine when the timer control generates events.
Note: The timer control has nothing to do with the Timer() function that you mastered in Lesson 7, "Functions and Dates." The timer control is a control that appears on the Toolbox window, whereas Timer() is a function that you add to your programs inside the Code window.
Concept: The timer control sits invisibly on the user's form,
waiting for a specified time interval to pass.
Figure 20.1 shows where the timer control appears on the toolbox. The timer control looks like a stopwatch. When you place the timer control on the form, the timer control looks like a stopwatch
there also. At least, to you, the programmer, the
timer control looks like a stopwatch; remember that the user can't see the timer control when the user runs the application.
Figure 20.1. The timer control is the
Toolbox window's stopwatch.
You can place the timer control on the form just as you place any other control. You can do the following:
When you place the timer control, place
the control out of the way of other controls. Keep in mind that the user won't see the timer control, so you can put the timer out of the way to keep it from interfering with the areas of the form where you'll
place the other controls.
Not only
is the placement of the timer control unimportant, but so is its size. No matter how you try to resize the timer control, Visual Basic refuses to change the size. The size of the control doesn't matter anyway because the user won't see the
control.
Figure 20.2 shows the Form window after you place the timer control in the window's lower-left corner.
Figure 20.2. The form with a single timer control.
Note: Any application can have multiple timer controls, just as any application can have multiple instances of the other controls.
Table 20.1 contains a list
of the timer property values available in the Property window for setting up the control. There aren't many timer control properties. If you think about the properties of the other controls, you may remember that most of the
properties are designed to aid
in the color and size selection of the controls (such as BackColor, Width, and so on). The timer control doesn't need all those extra properties because the user won't see the timer control and those properties would be
wasted.
Definition: A millisecond is one thousandth of a second.
Property | Description |
Enabled | Specifies whether the timer control can respond to events. |
Index | Indicates the subscript of the array if you store the timer control in a control array. |
Interval | Determines the timer interval, in milliseconds, when you want a timer event to occur. The Interval value can range from 1 to 65535. |
Left | Specifies the number of twips from the left edge of the Form window where the timer control resides. |
Name | Contains the name of the control. Unless you change the name, Visual Basic assigns the default names of Timer1, Timer2, and so on as you add timer controls. |
Tag | Unused by Visual Basic. This is for the programmer's use for an identifying comment applied to the option button. |
Top | Specifies the number of twips from the top edge of the Form window where the timer control resides. |
Generally, the most important timer control property is the Interval property. The other controls are common ones used by most of the other controls, and you're already familiar with most of them. The Interval property is
especially important
for determining the operation of the timer event procedures that you write for the timer control.
Warning: Remember that the largest positive integer that you can store using the Integer data type is 32767. Therefore, if you initialize the timer's Interval property using a variable, be sure that you use a Long Integer variable or one of the floating-point variables (Single or Double) to hold the initial value.
Before studying what code to put in timer control event procedures, you need to understand that there is only one event available for the timer control. Not only are there just a
handful of timer control properties, there is only a single kind of event
procedure that you can write for the timer control.
Timer is the event reserved for timer controls. Therefore, if you name a timer control tmrAlarm, the event for that
timer control will be called tmrAlarm_Timer(). To open that event, you can double-click the time control that you place on a form, or
select the Event from the Code window's Proc dropdown list to open the Timer event procedure.
Note: Visual Basic distinguishes between the Timer event procedure from the built-in Timer() function by the context of how you use the Timer procedure or function.
Windows imposes a limit on the number of timer controls that you can add to an application at any one time. If you attempt to add more timer controls than Windows allows at the time, Visual Basic displays the error message
shown in Figure 20.3. Windows
can support only a limited number of timer controls (usually, Windows can handle at least 15 timer controls within a single application). Windows wouldn't be able to keep track of all of the time intervals properly, owing to
timing conflicts and slowdowns
that occur, if you were to use too many timer controls.
Figure 20.3. The error message that you'll receive if you use too many timers.
Review:
The timer control has few properties and even fewer events. There is no need to specify timer control size and color properties because the user can't see the timer control and these events would be
meaningless.
Concept: The Interval property determines how much time elapses between
timer-generated events. Whereas other controls generate events in response to the user's input, the timer sits in the background,
generating events on its own at preselected time intervals.
Use the timer control to execute an event procedure at
a preselected time interval. When you place a timer control on a form, the timer's Interval property contains the number of milliseconds that pass before the timer's Timer() event procedure
executes.
Suppose that you place a timer event on the
control and set the timer's Interval property to 10000. If you name the timer event tmrSecond, the tmrSecond_Timer() event procedure executes every 10,000 milliseconds, or once every second.
Stop and Type:
Figure 20.4 shows the CLOCK.MAK application that you can load and run from this book's companion disks. The CLOCK.MAK application updates the time every second. The option button determines
whether you hear a beep every second that the
clock updates. The timer control is named tmrClock. Listing 20.1 contains the code for the tmrClock_Timer() event procedure that updates the time on the digital display, and beeps.
Figure 20.4. Watch the time update
every second.
Review: Initialize the Interval property with a value that represents the number of milliseconds that must pass between timer events. The Timer event procedure will then
automatically execute every time that
the Interval's time passes.
Listing 20.1. A digital clock's Timer event procedure code.
1: Sub tmrClock_Timer () 2: ' Beep every second if the check box 3: ' is set. Also, update the value of the clock 4: ' 5: ' This event procedure executes every second 6: ' (or every 1,000 milliseconds) because the 7: ' timer control's Interval value is 1000 8: If (chkBeep.Value) Then 9: Beep 10: End If ' Don't beep if option button not set 11: ' Update the time inside the label 12: lblClock.Caption = Time$ 13: End Sub
Analysis: Line 1 shows that the name of the
application's timer control is tmrClock. Therefore, that control's single event procedure is named tmrClock_Timer(). The timer control's Interval property is set to
1000 (milliseconds), so tmrClock_Timer() executes once every second.
Lines 8
through 10 check the check mark box to see whether the user wants the second beep or not. If the check box is checked, and therefore its Values property will be True, line 9 executes.
Line 12 then updates the value of the large clock label in the
center of the form. The Time$ function accesses the computer's clock every second because this event procedure executes every second.
Figure 20.5 shows CLOCK.MAK's Form window during the program's development. Notice the timer control sitting in
the lower-left corner of the screen. This timer control doesn't appear when the user runs the program, but the timer control's involvement in
the program is crucial because the timer control triggers the only event procedure in the entire application.
Figure 20.5. The timer control doesn't display in the running program.
Concept: The Interval property holds a maximum value of 65535. 65535 allows for a time interval of only a little more than a minute. If you write timer events that
need to execute less frequently than every
minute, you need to add code that keeps the timer event from running every time the timer event executes.
Suppose, for example, that you wanted to warn the user to select File Save every five minutes.
Anytime that you need something to happen once each time period, whatever that time period may be, use the timer control. To display the File Save message box
every five minutes, you could do the following:
Stop and Type: Listing 20.2 contains a timer event procedure that executes a message box statement every five minutes. The timer event executes every
minute, owing to the timer's Interval value of 60000. One
simple way to accomplish displaying the message box every five minutes is to define a module variable named MinCount that counts the minutes that go by and executes the message box statement every
time that MinCount reaches 5. Notice that, at the top of
Listing 20.2, you'll find the (general) declarations procedure that defines a module-level variable named MinCount. MinCount won't lose its former value between event procedure executions because
MinCount is a module variable and isn't locally defined
inside tmrMinute_Timer().
Review: When you need to execute code that must occur in time intervals greater than milliseconds, seconds, or
one-minute intervals, define a module-level variable to keep track of multiple occurrences of
second or minute time intervals.
Listing 20.2. Executing a timer event every five minutes.
1: ' Inside the (general) procedure 2: ' Define a module variable to keep 3: ' track of one-minute time intervals 4: Option Explicit 5: Dim MinCount As Integer ' Begins at zero 6: 7: Sub tmrMinute_Timer () 8: ' Ensures that a message box appears only every 9: ' five minutes despite the fact that this 10: ' event procedure executes every passing minute 11: MinCount = MinCount + 1 ' Raise minute count 12: If (MinCount = 5) Then 13: MsgBox "It's time to save your file!" 14: MinCount = 0 ' Reset the minute count 15: End If 16: End Sub
Analysis: Line 5 defines the module variable named MinCount. All defined variables begin with initial values of zero. Remember
that the timer named tmrMinute that executes the Timer subroutine procedure in this
example would contain an Interval value of 60000, so the tmrMinute_Timer() event procedure executes every minute that goes by.
Once the minute count reaches 5,
five minutes will have gone by since the MinCount variable was defined or since the last time that this event procedure executed. Therefore, line 13 displays the message box and line 14 resets the minute count to zero
again so that the counting towards
five minutes will begin to happen again. If, however, the minute count has not reached 5, the If condition is false and the subroutine terminates without displaying the message box.
You can't set a timer control to trigger an event at a specific single period in time. The timer control does not work like an alarm that goes off at a specific
point in time.
Concept: The timer control executes its Timer event procedure every time that the defined Interval passes. The timer control doesn't act as an alarm, however, executing an event procedure
at a preset time. You
can program the Timer event procedure, however, to simulate an alarm clock or a calendar reminder.
The timer control triggers a repeated event over and over. When you write a timer event procedure, the code inside the
procedure must be able to handle its own execution every time an event occurs. If you do want to execute a routine once at a
preset time, you'll have to write the event procedure to execute repeatedly (once each preset time interval); the code then
must check to see whether the PC's time equals that of the preset time that you're waiting on.
Stop and Type: Listing 20.3 contains the code needed to turn CLOCK.MAK into a wake-up alarm program. You can
find the alarm code on this book's disk under the project filename ALARM.MAK file. When you run the
program, you'll see an extra command button labeled Set Alarm. When you click Set Alarm, an input box appears asking for a time to wake up. When you enter
a correct time (the program loops until the you enter a correct time or choose Cancel), the set alarm
time appears to the right of the command button as shown in Figure 20.6 and a message box alarm goes off when that time is reached.
Review: When writing an alarm or calendar program, remember that the Timer event will always execute continuously, at least every 65,535 milliseconds because 65535 is the largest value that you can store in a
timer
control's Interval property. When the Timer event executes, your code can check the current time (or date if you write a date-checking calendar program) to see whether an alarm time has been reached.
Listing 20.3. Code
that sets an alarm and waits to wake up.
1: ' Define a module variable used in two 2: ' different procedures. The module variable 3: ' cannot lose its value between runs. 4: Option Explicit 5: Dim TimeSet As Variant 6: 7: Sub cmdSet_Click () 8: ' Ask the user for an alarm time to set 9: ' Keep looping until the user: 10: ' Enters a valid time or 11: ' clicks the Cancel command button 12: Do 13: TimeSet = InputBox("Enter a 24-hour time to wake up", "Time") 14: If (TimeSet = "") Then ' Check for Cancel 15: Exit Sub ' User pressed Cancel 16: End If 17: Loop Until IsDate(TimeSet) ' Keep asking if invalid 18: ' If here, the user entered a value that can 19: ' be converted to a valid time value. Now, 20: ' convert the Variant data to a date/time type 21: TimeSet = CVDate(TimeSet) 22: ' Display the wake-up time in a label 23: lblSet.Caption = "Alarm @ " & TimeSet 24: End Sub 25: 26: Sub tmrClock_Timer () 27: ' Sound an alarm if the set time has been hit 28: ' just now or perhaps bypassed by a fraction 29: Dim ctr As Integer 30: 31: If (chkBeep.Value) Then ' Second beep if needed 32: Beep 33: End If 34: lblClock.Caption = Time$ ' Update the screen's clock 35: 36: ' Sound the alarm if the wake up time has been 37: ' passed (also, make sure a time has been set) 38: If (Time >= TimeSet) And (lblSet.Caption <> "No alarm") Then 39: For ctr = 1 To 50 40: Beep ' Wake up!!! 41: Next ctr 42: MsgBox "W-a-k-e U-p-!-!-!", MB_ICONEXCLAMATION, "Alarm" 43: lblSet.Caption = "No alarm" ' To keep alarm from resounding 44: End If 45: End Sub
Output: Figure 20.6 shows what happens when the user sets a time that's about to trigger an alarm.
Figure 20.6. An alarm is ready to go off.
When the alarm sounds,
the user hears a wake-up series of beeps and sees the message box shown in Figure 20.7.
Figure 20.7. It's time to wake the user.
Analysis: Line 1 through 5
contains the (general) code that defines a module variable named TimeSet that will hold the user's wake-up time. The reason that you often must define module variables when dealing
with the Timer event, instead of using an argument list to pass values, is
because Visual Basic generates the Timer event and there is no way to request that Visual Basic generate a Timer event procedure that receives or sends arguments. Therefore, any
variable that you use inside a Timer event procedure must be a module or
global variable if you want to initialize that variable elsewhere and use that variable inside the Timer procedure.
Line 7 begins the procedure that requests the wake-up alarm time from the user. The subroutine contains a loop in lines 12 through
17 that asks the user for a time, and keeps asking until the user enters a valid time or until the user presses the Cancel
command button.
Line 21 then converts the user's variant variable that contains a valid time (thanks to the IsDate()
function call on line 17, which ensured that the user entered a valid time) to a date format that you can use to compare against the Time$() function in
the Timer() event procedure later. Line 23 changes the default caption of No alarm next to the Set
Alarm command button to the newly set wake-up time.
Caution: If the user enters only a date with no time, line 17's IfDate() function passes the date along. There is no way to check for an individual time using a built-in function.
Line 26 begins the Timer event procedure. Lines 31 through 33 check to see whether the second beeping should continue (the user would have
selected the check box on the form if the beep is desired). Line 34 updates the large clock display on the screen
every second without fail.
Line 38 checks to see whether it's time for the alarm to sound. Owing to imperfections in Windows, it's
possible for the Timer event procedure to skip a second once in a while, perhaps because the user switched to another Windows program temporarily,
which sometimes causes a timer control to miss a beat. Therefore, line 38 checks to see whether the current
time is later than or equal to the set time using the >= operator. Also, line 38 checks to see whether an alarm is even set.
If the alarm time has been reached and an alarm is set, a For loop in lines 39 through 41 beeps the speaker for a
series of 50 beeps, and then line 42 displays a message box to awaken the user. Line 43 resets the caption now that an alarm just sounded,
so the program won't keep sounding the alarm every subsequent second that follows.
Write an application with three command buttons labeled 10 Seconds, 30 Seconds, 45 Seconds. When the user clicks one of the command buttons, display a seconds
countdown for the appropriate number of seconds. When the countdown finishes, beep five times
to tell the user that the countdown completed. You can use either three separate timer controls or modify one timer's interval value depending on the command
button selected by the user.