An introduction to the functions provided by the Windows API for controlling timers, reacting to their interrupts, and processing WM_TIMER messages.
The Windows operating system follows an event driven artchitecture. In other words, nothing happens unless triggered by an event, be it a keyboard, mouse or system generated event or interrupt. The Windows kernel manages this flow of events, and makes sure that the messages that embody them travel to the correct process for treatment.
The core of any Windows application is the message loop, and the window procedure which processes incoming messages. Given that the majority of events are user or system driven, and that processing only occurs when an application has the 'focus', we sometimes need some way to momentarily get Windows attention to do some processing in an application that is not driven by a user or system event.
There are 2 ways to do this - process in the message loop, during the so-called 'idle' time, or use timers. Timers are easy to manage, predictable, and offer a simple solution for an application that needs to update itself occasionally, rather than constantly.
A timer is created using the SetTimer funtion, which in the simples form looks like:
The return value is a reference to the timer, used to identify it when the time comes to destroy it. The first parameter is the owner window. The second parameter is usually a constant integer value used to identify messages coming from the timer, while the third parameter is the time, in milliseconds, after which the timer should post an interrupt. So, to set a one-minute timer, we could use code such as:
The fourth parameter is set to NULL, in this case. It is actually the address of a procedure to call when the timer expires, which is beyond the scope of this article. A timer will keep on generating interrupts until it is destroyed. We assume in the above that hwnd and ID_6°SECONDS are set to meaningful values by the application.
A timer is destroyed using the KillTimer function:
Success is indicated by a non-zero (TRUE) return value.
Between the SetTimer and KillTimer function calls, assuming that everything has gone according to plan, the parent window will receive WM_TIMER messages. Unlike processing menu selections or child window controls, the timer does not send a notification through the WM_COMMAND message. Instead, the WM_TIMER message provides notification interrupts for any timers belonging to the parent windows calling thread.
So, during the window procedure message processing, code such as the following can be inserted:
The timer ID, which is not the return value from SetTimer, but the ID given to SetTimer, is received by the message processing loop as the WPARAM part of the MSG structure containing the notification message. The LPARAM contains a pointer to the callback function that can be set as parameter four of the SetTimer function. In the examples we have used here, that value will be set to NULL.
Note that if a callback function is used, the WM_TIMER message is sent to that, rather than the main message queue.