How Do I Generate and Use Timer Events?

Back Up Next

Windows timers are handy devices when you want your application to receive a message at a regular interval. This "wake-up call" can be used in programs that must be constantly active, working in the background while still allowing other applications to run properly. Or you can use a Windows timer just to time certain events, such as the amount of time a splash window should stay on-screen. Whatever uses you can find for Windows timers—and there are a million of them—you'll discover that they often provide clever solutions for sticky problems.

When you start a Windows timer, it sends WM_TIMER messages to the window that owns it at whatever interval you set. For example, you can set a Windows timer to send messages every five milliseconds, five seconds, and even five minutes. It's all up to you. (Actually, due to the way your computer's system timer works, it's not possible to receive WM_TIMER messages from a single timer more often than about 18 times a second.)

The Solution

First, prepare your window class to receive timer events by adding the EV_WM_TIMER macro to the response table:

DEFINE_RESPONSE_TABLE1(TWndw, TFrameWindow)
  EV_WM_TIMER,
END_RESPONSE_TABLE;

The matching message-response function for the EV_WM_TIMER macro is EvTimer().
You must declare and define this function in your window class:

class TWndw : public TFrameWindow {
  public:
    TWndw(TWindow *parent, const char far *title);
  protected:
    void EvTimer(uint);
 
  DECLARE_RESPONSE_TABLE(TWndw);
};

void TWndw::EvTimer(UINT)
{
  // Handle timer event here.
}

To get a Windows timer going, call the function SetTimer(), which is an encapsulated OWL version of a Windows API function of the same name:

SetTimer(timerID, millisecs);

SetTimer( )'s two arguments are the timer ID (any nonzero number) and the number of milliseconds between WM_TIMER messages. If there is no timer available (Windows has only 32), SetTimer() returns NULL. Normally, you should check the return value and be prepared to handle the rare case when there is no timer left available.

You can call SetTimer() anywhere in your program that the window still has a valid handle (the function uses the window handle to attach the timer to the window). This means the first possible opportunity you have to set a timer in an OWL program is in your window class's SetupWindow() function.

After you call SetTimer(), WM_TIMER messages will start arriving at the interval you selected. OWL routes these messages to the EvTimer() function, where you can handle them any way you like.

When you're through with the timer, you must kill it by calling the OWL function KillTimer() (inherited from TWindow):

KillTimer(timerID);

This function's single argument is the timer's ID. Because this function also requires that the window's handle be valid, you must call it before the window is destroyed. Your last chance in an OWL program is the window's CleanupWindow() function.

In any window class derived from TWindow, there are two sets of initialization func-tions that create and destroy the associated window object. The class's constructor and destructor are good places to initialize or destroy, respectively, any program items that don't require a valid window handle. The SetupWindow() and CleanupWindow() functions, on the other hand, are a good place for any function calls or items that require your window to have a valid handle.

When overriding SetupWindow(), always remember to call the base class's SetupWindow() first thing in the function. Failure to do this may result in your window class not being correctly set up.


Copyright © 1998-2001 Yura Bidus. All rights reserved.