關於SetTimer函數的總結
在使用 SOUI 編寫Windows程序時,似乎曾經看到過 SOUI 中限制了 SetTimer
函數能啓動的定時器的個數,於是今天就去 MSDN 看了下Windows本身是否也限制了單個程序能啓動的定時器個數,於是就有了這篇總結。
先下結論好了:微軟在 MSDN 上並沒有寫明單個程序能啓動的定時器的個數。
但是,還是學到了不少關於使用 SetTimer
函數時之前所不知道的地方,下面就來說一說。
慣例,先上 MSDN 關於 SetTimer
函數的原型。
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
那麼在使用 SetTimer
函數時需要注意的地方是什麼呢。
在 MSDN 中關於 nIDEvent
參數有這樣的說明:
A nonzero timer identifier. If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated. 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. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored. If the call is not intended to replace an existing timer, nIDEvent should be 0 if the hWnd is NULL
上面這段話說了三點:
- 當
SetTimer
函數的第一個參數傳遞NULL
時,SetTimer
函數會忽略第二個參數,轉而啓動一個隨機的定時器並返回它的數值,當調用KillTimer
函數時需要使用該數值,而不是調用SetTimer
函數時傳遞的數值。 - 當
SetTimer
函數的第二個參數的數值是當前計時中的定時器的數值時,系統會將那個定時器重置,重新計時,計時數值爲最新設置的uElapse
數值。 - 關於
nIDEvent
的大小沒有限制。
也就是說,當 hWnd
爲 NULL
時,無論第二個參數傳遞的是什麼數值(傳遞 NULL
也行),系統啓動的都不是你所指定的那個定時器,所以需要自己手動保存好 SetTimer
函數返回的數值,留待以後調用 KillTimer
函數時使用。
而且還要說一點:當 hWnd
爲 NULL
時,調用線程還是會收到 WM_TIMER
消息的,但是 GetMessage
或 PeekMesage
獲取到的 MSG
數據中的 hWnd
爲 NULL
(跟 PostThreadMessage
同理)。所以默認情況下,在MFC中使用 SetTimer(NULL, uElapse, NULL)
或 ::SetTimer(NULL, NULL, uElapse, NULL)
時,在 OnTimer
函數中都是無法響應該定時器的,需要重寫MFC的 PreTranslateMessage
函數才能響應該定時器。
關於 lpTimerFunc
參數,MSDN 的說法也值得注意:
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER.
就是說:當 lpTimerFunc
不爲NULL
時,窗口過程響應WM_TIMER
時會執行該函數,並不會執行默認的窗口過程。
所以,在MFC中,如果不想重寫MFC的 PreTranslateMessage
函數的話,可以設定 lpTimerFunc
參數,這樣也能處理 hWnd
爲 NULL
的 SetTimer
函數了。
好了,上面就是本人在 MSDN 看到的關於 SetTimer
函數的一點總結了。本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。