There are three approaches to using timers:
A sample program using the first method is the topic of discussion of this section. The application is a standard windows application that starts a timer in the main routine, as shown below.
// Win+ -- Beeper1.cpp -- Timer Demonstration Program Number 1 import iplusplus; using nanespace core; enum { identity_of_timer = 1 }; result __stdcall client(handle, unsigned, parameter, parameter); int __stdcall WinMain(handle module_handle, handle previous, character* command, int show_command) { window_class<character> wclass; wclass.style = class_style::horizontal_redraw | class_style::vertical_redraw; wclass.procedure = client; wclass.extra = 0; wclass.window = sizeof(void*); wclass.module = module_handle; wclass.icon = load_icon(0, (const character*)icon_identity::application); wclass.cursor = load_cursor(0, (const character*)cursor_identity::arrow); wclass.brush = get_standard_object(standard_brush::white); wclass.name = L"Beeper1"; atom atom_name = register_class(&wclass); handle window = create_window(atom_name, L"Beeper1"); set_timer(window, identity_of_timer, 1000); show_window(window, show_command); windows::queue queue_message; while (get_message(&queue_message, 0, 0, 0)) { translate_message(&queue_message); dispatch_message(&queue_message); } return (int)queue_message.parameter1; }
This example makes no use of a timer callback function, so the parameter timer_procedure is allowed to default to null when the timer is created. When a timer message is received for this timer, the pointer to the callback function is null. The enumerator timerIdentity is arbitrary and set to 1. A timer interval of 1 second is chosen (1000 milliseconds).
Within the client window procedure, the static variable Alternate is used to oscillate between states upon receipt of a timer message - as shown below.
result __stdcall client(handle window_handle, unsigned identity, parameter parameter1, parameter parameter2) { static int Alternate = false; switch (identity) { ... case message::timer: { window_data* data = (window_data*)get_window_pointer(window_handle, 0); message_beep(message_box_style::ok); data->alternate = !data->alternate; invalidate_rectangle(window_handle, (const irectangle*)null, false); } break; ... } return 0; }
The window procedure
When a paint message is received, the window procedure operates as shown below.
case message::paint: { window_data* data = (window_data*)get_window_pointer(window_handle, 0); paint paint_structure; handle device_context = begin_paint(window_handle, &paint_structure); irectangle client; get_client_rectangle(window_handle, &client); handle brush_handle = create_solid_brush(data->alternate ? red_green_blue(255, 0, 0) : red_green_blue(0, 0, 255)); fill_rectangle(device_context, &client, brush_handle); end_paint(window_handle, &paint_structure); delete_object(brush_handle); } break;
Depending upon the value of alternate, the client is painted either red or blue - so that it oscillates between these two colors.
The window procedure stops the timer when it receives the message message::destroy - as shown below.
case message::destroy: cancel_timer(window_handle,timer_tdentity); break;
By now the reader should be thoroughly familiar with the concept of callbacks. A window procedure is a callback. Callbacks are also used by the various tree managers to compare items. Callbacks were also discussed in detail in the first chapter.
In the previous example, the message message::timer was coded to manage timer message processing; whereas, the program of this section allows timer messages to flow through to the default window procedure. That is not to say that timer messages are not generated - they are, but they are given default processing. The default action for a timer message is to invoke the associated timer callback (when one is present). A callback may be specified to the function set_timer through the fourth parameter. By way of proceeding in this manner, a timer callback has been defined for the sample of this section and it is shown below.
void __stdcall timer(handle window_handle, unsigned message, ulong identity, unsigned time) { window_data* data = (window_data*)get_window_pointer(window_handle, 0); message_beep(message_box_style::ok); data->alternate = !data->alternate; irectangle client_rectangle; get_client_rectangle(window_handle, &client_rectangle); handle device_context = get_device_context(window_handle); handle brush = create_solid_brush(data->alternate ? red_green_blue(255, 0, 0) : red_green_blue(0, 0, 255)); fill_rectangle(device_context, &client_rectangle, brush); release_device_context(window_handle, device_context); delete_object(brush); }
The timer callback obtains a device context that is used to draw in the window. The associated data structure also contains a variable called alternate - which is used to alternate between states. Depending upon the state, the device context that is obtained is used to paint the client window red or blue. A beep is also issued.
The third method of creating a timer uses the win+ function set_timer to create a queue timer. In this case, there is no associated window and the window handle is null on the timer messages that are placed in the queue. The function dispatch_message calls the associated timer callback routine directly.