說道定時器,很多人都會想到Windows定時器SetTimer吧!其實,項目里面原本確實是使用這種方法實現動畫效果的,但是后來問題出現了!由於WM_TIMER消息優先級比較低,常常被丟失,導致一個WM_MOUSEMOVE消息都會影響整個動畫的效果。
這時我就考慮,是否能給定時器創建一個單獨的線程,接着就發現了“多媒體定時器”這個東西。它是一個高精確度定時器,一般的Windows定時器只能精確到55ms,而多媒體定時器能精確到10ms內。同時,在啟動一個多媒體定時器的同時,會自動創建一個線程,專門負責定時器控制。不僅如此,多媒體計時器具有較高的優先級(記得是15),因此能夠滿足實時控制的需求。但是這也為它帶來了不利的因素,同時對於定時器響應函數的內容也有一些限制,具體情況有時間再詳細說明下!
為了學會使用它,我研究了很多相關資料,其中經典的算《C++builder 深度歷險》這本書了。嘿嘿~ 閑暇的時間看了下C++builder,又收獲了一些其它知識。
首先,簡要介紹下幾個重要的函數,具體說明見MSDN!
1)MMRESULT timeGetDevCaps( LPTIMECAPS ptc, UINT cbtc );
功能:獲得計時器所支持的解析度范圍。
2)MMRESULT timeBeginPeriod( UINT uPeriod );
功能:調整計時器的解析度,用在啟動計時器之前。
3)MMRESULT timeEndPeriod( UINT uPeriod );
功能:調整計時器的解析度,用在結束計時器之后。這兩個函數通常是成對出現。
4)MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent );
功能:設置並啟動一個計時器
5)MMRESULT timeKillEvent( UINT uTimerID );
功能:取消一個定時器
好了!廢話不多少,直接跳到使用方法階段:
1)設置並啟動定時器
1 if (timeBeginPeriod(5) == TIMERR_NOERROR ) 2 { 3 m_uTimerID = timeSetEvent(30,5,TimeProc,(DWORD)GetSafeHwnd(),TIME_PERIODIC); 4 }
2)取消定時器
1 timeKillEvent(m_uTimerID); 2 timeEndPeriod(5);
3)定時器處理函數
1 void _stdcall TimeProc(UINT uTimerID,UINT uMessage,DWORD dwUser,DWORD dw1,DWORD dw2) 2 { 3 ::SendMessage((HWND)dwUser,UM_TIMER_PROC,0,0); 4 }
Tip: 定時器處理函數一般定義為全局函數,而函數內部使用的方法也只能是全局變量或函數!
最后,不要忘記加上以下頭文件和動態鏈接庫:
1 #pragma comment(lib,"Winmm.lib") 2 3 #include <Mmsystem.h>