What is a counter?
A timer is an input device that periodically notifies the application every time it passes through a specified interval. When your program notifies windows of the time interval, for example, "notify me every 10 seconds", then Windows sends a periodic wm_timer message to your program to indicate that the time is up.
We can assign a timer to a Windows program by calling the settimer function. Settimer has an integer parameter with a time interval ranging from 1 ms to 4,294,967,295 ms (nearly 50 days). This value indicates how often windows sends wm_timer messages to programs. For example, if the interval is 1000 milliseconds, Windows will send a wm_timer message to the program every second.
When your program runs out of the timer, it calls the killtimer function to stop the timer message. When processing wm_timer messages, you can call the killtimer function to compile an "instant" timer. In addition to destroying timer events created by calling settimer, killtimer also clears unprocessed wm_timer messages in the message queue, so that the program will not receive wm_timer messages after calling killtimer.
The following describes how to use a timer.
How to use a timer?
If you need to use a timer during the entire program execution, you will have to call settimer from the winmain function or when processing the wm_create message, killtimer is called when you exit winmain or respond to the wm_destroy message. Based on the parameter used to call settimer, you can use the timer in either of the following two methods.
Method 1
This is the most convenient method. It allows Windows to send the wm_timer message to the normal window of the application. The settimer call is as follows:
Settimer (hwnd, 1, uimsecinterval, null );
The first parameter is the window handle that will receive the wm_timer message during the window process. The second parameter is the timer ID, which is a non-zero value. In this example, it is assumed to be 1. The third parameter is a 32-bit unsigned integer, which specifies a time interval in milliseconds. A value of 60,000 will enable Windows to send a wm_timer message every minute.
You can call
Killtimer (hwnd, 1 );
Stop the wm_timer message at any time (even if the wm_timer message is being processed ). The second parameter of this function is the same timer ID used in the settimer call. Before terminating the program, you should stop any active timer in the Response Message wm_destroy.
When you receive a wm_timer message ① In the window process, the wparam parameter is equal to the ID value of the timer (1 in the above case), and The lparam parameter is 0. To make the program more readable, you can use # define to describe different timer IDs:
# Define timer_sec 1
# Define timer_min 2
Then you can use two settimer calls to set two Timers:
Settimer (hwnd, timer_sec, 1000, null );
Settimer (hwnd, timer_min, 60000, null );
Wm_timer processing is as follows:
Casewm_timer:
Switch (wparam)
{
Case timer_sec:
// Processing once per second
Break;
Case timer_min:
// Processing every minute
Break;
}
Return 0;
If you want to set an existing timer to a different interval, you can call settimer again with different time values.
Method 2
The first method to set the timer is to send the wm_timer message to the common window process, while the second method is to allow windows to directly send the timer message to another function of your program.
The function that receives these timer messages is called a callback function, which is a function called by windows in your program (as mentioned in the fourth round ). Tell the address of the function in windows, and then call the function in windows. This seems familiar, because the Window Process of the program is actually a callback function. When registering a window class, you need to inform windows of the function address. When sending a message to a program, Windows will call this function.
Like the window process, the callback function must also be defined as Callback because it is called by the program code segment of the Windows slave program. The parameters of the callback function and the return value of the callback function depend on the purpose of the callback function. In the timer-related callback function, the input parameters are the same as those in the window process. The timer callback function does not return values to Windows.
The following callback function is called timerproc (you can select any name that does not conflict with other terms). It only processes wm_timer messages:
Void callback timerproc (hwnd, uint message, uint itimerid, DWORD dwtime)
{
// Process the wm_timer message
}
The hwnd parameter of timerproc is the window handle specified when settimer is called. In Windows, only wm_timer messages are sent to timerproc, so the message parameter is always equal to wm_timer. The itimerid value is the timer ID, and the dwtimer value is compatible with the return value from the gettickcount function. This is the number of milliseconds that have elapsed since Windows was started.
The settimer in the following format is required to set the timer using the first method:
Settimer (hwnd, itimerid, imsecinterval, null );
When you use the callback function to process wm_timer messages, the fourth parameter of settimer is replaced by the callback function address, as shown below:
Settimer (hwnd, itimerid, imsecinterval, timerproc );
Let's look at an example.
1 # include <windows. h> 2 3 # define id_timer 1 4 5 6 lresult callback wndproc (hwnd, uint, wparam, lparam); 7 8 void callback timerproc (hwnd, uint, uint, DWORD ); 9 10 11 int winapi winmain (hinstance, hinstance hprevinstance, 12 13 pstr szline line, int icmdshow) 14 15 {16 17 static char szappname [] = "timer Demo "; 18 19 hwnd; 20 21 MSG; 22 23 wndclass; 24 25 26 27 wndclass. style = cs_hredraw | cs_vredraw; 28 29 wndclass. lpfnwndproc = wndproc; 30 31 wndclass. cbclsextra = 0; 32 33 wndclass. cbwndextra = 0; 34 35 wndclass. hinstance = hinstance; 36 37 wndclass. hicon = loadicon (null, idi_application); 38 39 wndclass. hcursor = loadcursor (null, idc_arrow); 40 41 wndclass. hbrbackground = (hbrush) getstockobject (white_brush); 42 43 wndclass. lpszmenuname = NULL; 44 45 wndclass. lpszclassname = szappname; 46 47 48 49 If (! Registerclass (& wndclass) 50 51 {52 53 MessageBox (null, text ("program requires Windows NT! "), 54 55 szappname, mb_iconerror); 56 57 Return 0; 58 59} 60 61 62 63 hwnd = createwindow (szappname," timer Demo ", ws_overlappedwindow, cw_usedefault, cw_usedefault, cw_usedefault, cw_usedefault, 70 71 null, null, hinstance, null); 72 73 74 75 showwindow (hwnd, icmdshow); 76 77 updatewindow (hwnd ); 78 79 80 81 While (getmessage (& MSG, null, 0, 0) 82 83 {84 85 translatemessage (& MSG); 86 87 Dispatchmessage (& MSG); 88 89} 90 91 return MSG. wparam; 92 93} 94 95 96 lresult callback wndproc (hwnd, uint message, wparam, lparam) 97 98 {99 100 switch (Message) 101 102 {103 104 case wm_create: 105 106 settimer (hwnd, id_timer, 1000, timerproc); 107 108 109 return 0; 110 111 112 case wm_destroy: 113 114 killtimer (hwnd, id_timer); 115 116 postquitmessage (0); 117 118 retu Rn 0; 119 120} 121 122 return defwindowproc (hwnd, message, wparam, lparam); 123 124} 125 126 127 void callback timerproc (hwnd, uint message, uint itimerid, DWORD dwtime) 128 129 {130 131 static bool fflipflop = false; 132 133 hbrush; 134 135 HDC; 136 137 rect RC; 138 139 fflipflop =! Fflipflop; 140 141 142 143 getclientrect (hwnd, & rc); 144 145 HDC = getdc (hwnd); 146 147 hbrush = createsolidbrush (fflipflop? RGB (255, 0, 0): RGB (255, 148); 149 // This judgment statement in parentheses I guess everyone knows it, I don't explain 150 151 fillrect (HDC, & rc, hbrush); 152 153 releasedc (hwnd, HDC); 154 155 deleteobject (hbrush); 156 157}
The timer interval is set to 1 second. When it receives the wm_timer message, it changes the color of the display area from blue to red or from red to blue.
The Program sets a timer when processing the wm_create message in the window process. During wm_timer message processing, the value of bflipflop is flipped and the window is invalid to generate the wm_paint message. During wm_paint message processing, call getclientrect to obtain the rect structure of the window size, and call fillrect to change the color of the window.
Is the timer accurate?
Unfortunately, it is not accurate for the following reasons.
Cause 1: Windows timers are a relatively simple extension of timer logic constructed by PC hardware and rom bios. Back to Windows's previous MS-DOS programming, applications can implement a clock or timer by capturing BIOS interruptions called Timer tick. These interruptions occur every 54.915 milliseconds, or about 18.2 times per second. Some programs written for the MS-DOS themselves capture this hardware interrupt for clock and timer. This is the result of the 4.772720 MHz division of the original ibm pc microprocessor. Windows applications do not intercept BIOS interruptions. On the contrary, Windows itself handles hardware interruptions so that applications do not have to process them. In Windows 98, the timer has the same resolution of 55 milliseconds as the PC timer. in Microsoft Windows NT, the timer resolution is 10 milliseconds. That is, Windows applications cannot receive wm_timer messages at a frequency higher than these resolutions (18.2 times per second in Windows 98 and about 100 times per second in Windows NT. The time interval specified in settimer is always an integer multiple of the tick count after the tail truncation. For example, if the interval of 1000 ms is divided by 54.925 ms, 18.207 tick is obtained and 18 tick is taken at the end of the screenshot, which is actually 989 Ms. For each interval less than 55 milliseconds, each tick will generate a wm_timer message.
It can be seen that the timer cannot send the wm_timer message strictly according to the specified interval, and the difference is always several milliseconds.
The timer is still inaccurate even if the difference in milliseconds is ignored. Please refer to reason 2:
The wm_timer message is placed in a normal message queue and arranged together with other messages. Therefore, if the interval specified in settimer is 1000 milliseconds, therefore, it is not guaranteed that the program will receive a wm_timer message every 1000 ms or 989 Ms. If other programs run for more than one second, during this period, your program will not receive any wm_timer message. In fact, Windows processes wm_timer messages very similar to wm_paint messages. These two messages are of low priority, and the program receives them only when there are no other messages in the message queue.
Wm_timer is also similar to wm_paint: Windows cannot continuously put multiple wm_timer messages into the message queue, but combines redundant wm_timer messages into one message. Therefore, the application will not receive multiple such messages at a time, although two wm_timer messages may be obtained in a short time. The application cannot determine the number of wm_timer messages "lost" caused by this processing method.
It can be seen that wm_timer messages cannot be processed by the application in a timely manner, and the delay of wm_timer in the message queue may not be calculated in milliseconds.
From the preceding two points, you cannot use the one-second count method when processing wm_timer. If you want to implement a clock program, you can use a system time function such as getlocaltime. In the clock program, the timer function is to call getlocaltime regularly to obtain a new time and refresh the clock screen, of course, the interval for refreshing is equal to or less than 1 second.
① Wm_timer message.
Wparam is the ID of the counter: If you need to set multiple timers, different counters are used for each timer.
The ID of the timer. The value of wparam varies with the wm_timer message transmitted to the window.
Lparam is the pointer to timerproc. If timerproc is not specified when settimer is called (its parameter value
Is null, that is, the first usage), then lparam is 0, obviously in the second usage, this value is not 0.
Note: For more information, see Windows timer.