VC++ 高精度定时timeSetEvent和回调成员方法
Platform SDK: Windows Multimedia中的timeSetEvent函数和timeKillEvent函数可以启动和停止一个精度达到1ms的高精度定时器。 原型: 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. 事件延迟,毫秒。如果这个值不在定时器支持的最小和最大延时之间的话,函数将返回一个错误。 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. 定时器的分辨力,毫秒。小的数值表示高的分辨力;分辨力为0表示周期事件应该以允许的最高精度发生。尽管如此为减小系统开销,你应该使用适合你应用的最大值。 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); 指向回调函数的指针。发生单次事件时它被调用一次,发生周期事件时,它被周期调用。如果fuEvent是TIME_CALLBACK_EVENT_SET或TIME_CALLBACK_EVENT_PULSE标识,这时lpTimeProc被翻译成事件的一个句柄。根据单个事件或周期事件的完成,事件会被设置或触发。对于fuEvent的其它值,lpTimeProc被翻译为一个函数指针,它具有下面的签名:void (CALLBACK)(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); dwUser User-supplied callback data. 用户提供的回调函数数据 fuEvent Timer event type. This parameter may include one of the following values. 定时事件类型。这个参数可能包含以下值的一个:
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.) 如果成功返回定时器事件的一个标识符,否则返回一个错误。如果它失败了,这个函数返回NULL,定时器事件不会被创建。(这个标识符同样会被传递给回调函数)。 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. 每个对timeSetEvent的周期性定时调用都需要一个相应的timeKillEvent函数的调用。 通过TIME_KILL_SYNCHRONOUS方式创建一个事件,TIME_CALLBACK_FUNCTION标识在timeKillEvent调用后将阻止事件的发生。
由于在VC++中,成员方法都有一个this指针,不能将成员方法直接作为回调函数使用。解决的方法是使用一个static的方法作为回调函数。但是如果仅仅这样的话,我们将不能使用实例中的成员变量和成员方法等。这意味着在很多情况下回调达不到我们的需求。参考网上的一些方法,注意到timeSetEvent有一个DWORD类型的用户提供的回调函数数据dwUser ,在此处如果将对象的this指针传入,然后在静态方法内通过this指针来调用成员方法。这样就可以间接的实现成员函数的回调了。这个方法是最简单的方法。但是它也存在明显的缺陷,那就是调用深度多了一级,可能引发执行效率的问题。网上也有很好的解决方法,但是会比较复杂。需要分析清成员函数调用的机制,甚至还需要编写一些汇编的代码,在这里就先不介绍了。 Example: 在类CTimerCallbackDlg中 protected: virtual void OnMMTimer();//声明要回调的成员方法 //作为回调函数的静态方法 static void CALLBACK TimerCallBack(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { CTimerCallbackDlg * pThis=(CTimerCallbackDlg*)dwUser;//由this指针获得实例的指针 pThis->OnMMTimer();//调用要回调的成员方法 } /***********************************/ //一个定时器的使能禁能按钮 void CTimerCallbackDlg::OnTimerEn() { // TODO: Add your control notification handler code here if(!m_en) { //返回定时器的id,用于停止定时器,回调静态函数,传入this指针 m_timerId=timeSetEvent(100,100,&TimerCallBack,(DWORD)this,1); m_en=true; SetDlgItemText(IDC_TimerEn,"Stop"); } else { //关闭定时器 timeKillEvent(m_timerId); m_en=false; SetDlgItemText(IDC_TimerEn,"Start"); } }
|
|