How Do I Generate and Use Timer Events?
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 timersand there are a million of themyou'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.