## Visual Basic in 12 Easy Lessons vel20.htm

- What You'll Learn
- Introducing the Timer Control
- Using the Timer Control
- Events That Occur Infrequently
- The Timer Is Not an Alarm
- Homework
  - General Knowledge
  - Write Code That...
  - Extra Credit

#
Lesson 10, Unit 20

##
Time's Up

###
What You'll Learn

- Introducing the timer control
- Using the timer control
- Events that occur infrequently
- The timer is not an alarm

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.

###
Introducing the Timer Control

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:

- Double-click the timer control so that it appears in the middle of the form. You then can drag the control to the location where you want the control to reside.
- Click and drag the timer control to the position on the form where you want the control to reside.

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.

Table 20.1. The timer control properties.

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.

###
Using the Timer Control

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.

###
Events That Occur Infrequently

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:

1. Place a timer control on the application's form.
2. Determine how many milliseconds there are in five minutes. There are 1,000 milliseconds in each second. There are 60,000 milliseconds in each minute. Therefore, there are 300,000 milliseconds every five minutes.
3. The number of milliseconds exceeds 65,535 (the maximum allowable value for the Interval property) so you'll have to divide the time period into more manageable units of milliseconds, seconds, or one minute intervals.
   Five minutes is easily divided into five one-minute time intervals. One minute is equal to 60,000 milliseconds. Therefore, you'll have to set the Interval property to 60000 and control the File Save message box display so that the message box appears only once out of every five times that the event procedure executes.

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.

###
The Timer Is Not an Alarm

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.

###
Homework

####
General Knowledge

1. What control keeps track of elapsed time?
2. What is the most important property of the timer control?
3. Why doesn't the timer control contain any color or size properties?
4. What does the user see in the upper-left corner of a executing program's form when you place a timer control in the upper-left corner of a form?
5. True or false: The user triggers timer events.
6. What time value is measured by the timer control's Interval property?
7. True or false: An application can have, at most, one timer control.
8. What is a millisecond?
9. How much time does ten thousand milliseconds measure?
10. How much time does sixty thousand milliseconds measure?
11. What Name prefix do programmers usually assign to the timer control?
12. What problem can you run into if you attempt to set a timer's Interval property with an integer variable?
13. What is the name of the only event procedure available for time controls?
14. True or false: You can set the timer's Interval property to trigger an event at a certain preset time.
15. Why would Visual Basic sometimes be error prone if you were to test the Time$() value against an exact time match?

####
Write Code That...

1. Modify the code in project 7 so that the time display updates every second. The update should occur no matter which time zone the user selects.

####
Extra Credit

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.