VC++ 高精度定時(shí)timeSetEvent和回調(diào)成員方法
Platform SDK: Windows Multimedia中的timeSetEvent函數(shù)和timeKillEvent函數(shù)可以啟動(dòng)和停止一個(gè)精度達(dá)到1ms的高精度定時(shí)器。 原型: MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent ); Parameters uDelay Event delay, in milliseconds. If this value is not in the range of the minimum and maximum event delays supported by the timer, the function returns an error. 事件延遲,毫秒。如果這個(gè)值不在定時(shí)器支持的最小和最大延時(shí)之間的話,函數(shù)將返回一個(gè)錯(cuò)誤。 uResolution Resolution of the timer event, in milliseconds. The resolution increases with smaller values; a resolution of 0 indicates periodic events should occur with the greatest possible accuracy. To reduce system overhead, however, you should use the maximum value appropriate for your application. 定時(shí)器的分辨力,毫秒。小的數(shù)值表示高的分辨力;分辨力為0表示周期事件應(yīng)該以允許的最高精度發(fā)生。盡管如此為減小系統(tǒng)開銷,你應(yīng)該使用適合你應(yīng)用的最大值。 lpTimeProc Pointer to a callback function that is called once upon expiration of a single event or periodically upon expiration of periodic events. If fuEvent specifies the TIME_CALLBACK_EVENT_SET or TIME_CALLBACK_EVENT_PULSE flag, then the lpTimeProc parameter is interpreted as a handle to an event object. The event will be set or pulsed upon completion of a single event or periodically upon completion of periodic events. For any other value of fuEvent, the lpTimeProc parameter is interpreted as a function pointer with the following signature: void (CALLBACK)(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); 指向回調(diào)函數(shù)的指針。發(fā)生單次事件時(shí)它被調(diào)用一次,發(fā)生周期事件時(shí),它被周期調(diào)用。如果fuEvent是TIME_CALLBACK_EVENT_SET或TIME_CALLBACK_EVENT_PULSE標(biāo)識(shí),這時(shí)lpTimeProc被翻譯成事件的一個(gè)句柄。根據(jù)單個(gè)事件或周期事件的完成,事件會(huì)被設(shè)置或觸發(fā)。對(duì)于fuEvent的其它值,lpTimeProc被翻譯為一個(gè)函數(shù)指針,它具有下面的簽名:void (CALLBACK)(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); dwUser User-supplied callback data. 用戶提供的回調(diào)函數(shù)數(shù)據(jù) fuEvent Timer event type. This parameter may include one of the following values. 定時(shí)事件類型。這個(gè)參數(shù)可能包含以下值的一個(gè):
The fuEvent parameter may also include one of the following values. fuEvent也包含下面的值
Return Values Returns an identifier for the timer event if successful or an error otherwise. This function returns NULL if it fails and the timer event was not created. (This identifier is also passed to the callback function.) 如果成功返回定時(shí)器事件的一個(gè)標(biāo)識(shí)符,否則返回一個(gè)錯(cuò)誤。如果它失敗了,這個(gè)函數(shù)返回NULL,定時(shí)器事件不會(huì)被創(chuàng)建。(這個(gè)標(biāo)識(shí)符同樣會(huì)被傳遞給回調(diào)函數(shù))。 Remarks Each call to timeSetEvent for periodic timer events requires a corresponding call to the timeKillEvent function. Creating an event with the TIME_KILL_SYNCHRONOUS and the TIME_CALLBACK_FUNCTION flag prevents the event from occurring after the timeKillEvent function is called. 每個(gè)對(duì)timeSetEvent的周期性定時(shí)調(diào)用都需要一個(gè)相應(yīng)的timeKillEvent函數(shù)的調(diào)用。 通過(guò)TIME_KILL_SYNCHRONOUS方式創(chuàng)建一個(gè)事件,TIME_CALLBACK_FUNCTION標(biāo)識(shí)在timeKillEvent調(diào)用后將阻止事件的發(fā)生。
由于在VC++中,成員方法都有一個(gè)this指針,不能將成員方法直接作為回調(diào)函數(shù)使用。解決的方法是使用一個(gè)static的方法作為回調(diào)函數(shù)。但是如果僅僅這樣的話,我們將不能使用實(shí)例中的成員變量和成員方法等。這意味著在很多情況下回調(diào)達(dá)不到我們的需求。參考網(wǎng)上的一些方法,注意到timeSetEvent有一個(gè)DWORD類型的用戶提供的回調(diào)函數(shù)數(shù)據(jù)dwUser ,在此處如果將對(duì)象的this指針傳入,然后在靜態(tài)方法內(nèi)通過(guò)this指針來(lái)調(diào)用成員方法。這樣就可以間接的實(shí)現(xiàn)成員函數(shù)的回調(diào)了。這個(gè)方法是最簡(jiǎn)單的方法。但是它也存在明顯的缺陷,那就是調(diào)用深度多了一級(jí),可能引發(fā)執(zhí)行效率的問(wèn)題。網(wǎng)上也有很好的解決方法,但是會(huì)比較復(fù)雜。需要分析清成員函數(shù)調(diào)用的機(jī)制,甚至還需要編寫一些匯編的代碼,在這里就先不介紹了。 Example: 在類CTimerCallbackDlg中 protected: virtual void OnMMTimer();//聲明要回調(diào)的成員方法 //作為回調(diào)函數(shù)的靜態(tài)方法 static void CALLBACK TimerCallBack(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { CTimerCallbackDlg * pThis=(CTimerCallbackDlg*)dwUser;//由this指針獲得實(shí)例的指針 pThis->OnMMTimer();//調(diào)用要回調(diào)的成員方法 } /***********************************/ //一個(gè)定時(shí)器的使能禁能按鈕 void CTimerCallbackDlg::OnTimerEn() { // TODO: Add your control notification handler code here if(!m_en) { //返回定時(shí)器的id,用于停止定時(shí)器,回調(diào)靜態(tài)函數(shù),傳入this指針 m_timerId=timeSetEvent(100,100,&TimerCallBack,(DWORD)this,1); m_en=true; SetDlgItemText(IDC_TimerEn,"Stop"); } else { //關(guān)閉定時(shí)器 timeKillEvent(m_timerId); m_en=false; SetDlgItemText(IDC_TimerEn,"Start"); } }
|
|