MFC's CWnd::SetTimer
calls WinAPI's SetTimer
simply.
_AFXWIN_INLINE UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD))
{ ASSERT(::IsWindow(m_hWnd)); return ::SetTimer(m_hWnd, nIDEvent, nElapse,
lpfnTimer); }
But SetTimer and CWnd::SetTimer documents are not same.
nIDEvent
parameter
SetTimer
:
If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset.
CWnd::SetTimer
:
Specifies a nonzero timer identifier. If the timer identifier is unique, this same value is returned bySetTimer
. Otherwise,SetTimer
determines a new unique value and returns that. For a window timer (which has a NULL callback function), the value must be unique only for other windows timers that are associated with the current window. For a callback timer, the value must be unique for all timers in all processes. Therefore, when you create a callback timer, it is more likely that the returned value might differ from the value you specify.
SetTimer
does not depend on callback parameter and always replaces the existing timer. But CWnd::SetTimer
depends on callback parameter, and if callback specified, a new timer ID may be generated because the value must be unique for all timers in all processes.
SetTimer
:
If the function succeeds and the hWnd parameter is not NULL, then the return value is a nonzero integer. An application can pass the value of the nIDEvent parameter to the KillTimer function to destroy the timer.
CWnd::SetTimer
:
The timer identifier of the new timer if the function is successful. This value may or may not be equal to the value passed in through thenIDEvent
parameter. An application should always pass the return value to the KillTimer member function to kill the timer.
SetTimer
does not generate new timer id and does not return timer id, so call KillTimer
with nIDEvent
parameter. But CWnd::SetTimer
generates new timer id in some case, so call KillTimer
with the returned value.
Thus, which document is correct?
I want to use WinAPI SetTimer
with a callback and it works on my pc. But if some platform does not replace the existing timer, I could not accept the callback timer.
MFC documentation is incorrect, as far as I can tell. I have tested extensively, and the timers always replace the previous timer, provided the window is the same. This is true with callbacks and without.
With a callback, I ran the following test:
static void CALLBACK MyTimerProc(HWND hWnd, UINT nMsg, UINT_PTR nIDEvent, DWORD dwTime) {
KillTimer(hWnd, nIDEvent);
}
...
timerID = SetTimer(2, 1000, MyTimerProc);
timerID = SetTimer(2, 1100, MyTimerProc);
timerID = SetTimer(4, 1200, MyTimerProc);
timerID = GetParentFrame()->SetTimer(4, 1300, MyTimerProc);
Results were (from VS debugger trace):
timerID=2
timerID=2
timerID=4
timerID=4
nIDEvent=2, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x0000000000140bd0
The last SetTimer call used a different window, which gave the same event twice. But every time, the return value is identical to the value passed for the timer. And the same value is used for nIDEvent.
The CWnd documentation is either out of date, or acting out of extreme caution--we know the return value is the ID, so we should always use that.
However, one statement is clearly false:
For a callback timer, the value must be unique for all timers in all processes
I just demonstrated I could use the same ID twice, within the same process, and still receive both events.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With