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.

定时事件类型。这个参数可能包含以下值的一个:

Value

Meaning

TIME_ONESHOT

Event occurs once, after uDelay milliseconds.

事件在uDelay毫秒后发生一次

TIME_PERIODIC

Event occurs every uDelay milliseconds.

事件每隔uDelay毫秒发生一次

The fuEvent parameter may also include one of the following values.

fuEvent也包含下面的值

Value

Meaning

TIME_CALLBACK_FUNCTION

When the timer expires, Windows calls the function pointed to by the lpTimeProc parameter. This is the default.

当定时器超时,Windows调用lpTimeProc参数所指向的函数。这时默认的。

TIME_CALLBACK_EVENT_SET

When the timer expires, Windows calls the SetEvent function to set the event pointed to by the lpTimeProc parameter. The dwUser parameter is ignored.

当定时器超时,Windows调用SetEvent函数来设置lpTimeProc参数所指向的事件。dwUser参数被忽略。

TIME_CALLBACK_EVENT_PULSE

When the timer expires, Windows calls the PulseEvent function to pulse the event pointed to by the lpTimeProc parameter. The dwUser parameter is ignored.

当定时器超时,Windows调用PulseEvent函数来触发lpTimeProc参数所指向的事件。dwUser参数被忽略。

TIME_KILL_SYNCHRONOUS

Passing this flag prevents an event from occurring after the timeKillEvent() function is called.

传递这个标识将在调用timeKillEvent()后阻止事件发生。

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");

       }

}

转载于:https://www.cnblogs.com/shenlanzifa/p/5288775.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`timeSetEvent` 是一个Windows API函数,用于设置定时器事件。它的原型如下: ```c++ MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent ); ``` 其中,`lpTimeProc` 参数是一个指向回调函数的指针,用于处理定时器事件。回调函数的原型如下: ```c++ void CALLBACK TimeProc( UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 ); ``` 在回调函数中,`uTimerID` 参数是定时器的标识符,`uMsg` 参数是一个预留参数,通常为 `TIME_TICK`,`dwUser` 参数是 `timeSetEvent` 函数调用时传入的 `dwUser` 参数,`dw1` 和 `dw2` 参数是一些保留参数,通常为0。 下面是一个简单的例子,演示如何使用 `timeSetEvent` 函数和回调函数处理定时器事件: ```c++ #include <Windows.h> #include <iostream> void CALLBACK TimeProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { std::cout << "Timer triggered! Timer ID: " << uTimerID << std::endl; } int main() { /* 设置定时器事件,每隔 1 秒触发一次 */ MMRESULT res = timeSetEvent(1000, 0, TimeProc, 0, TIME_PERIODIC); if (res == 0) { std::cerr << "Failed to set timer event" << std::endl; return 1; } /* 等待定时器触发 */ std::cout << "Waiting for timer..." << std::endl; system("pause"); /* 取消定时器事件 */ res = timeKillEvent(res); if (res == 0) { std::cerr << "Failed to kill timer event" << std::endl; return 1; } std::cout << "Timer event cancelled" << std::endl; return 0; } ``` 这个例子中,我们设置了一个每隔1秒触发一次的定时器事件,并在回调函数 `TimeProc` 中输出一条消息。程序运行后,会输出 "Waiting for timer...",等待定时器事件的触发。当定时器事件被触发时,会输出 "Timer triggered! Timer ID: xxx",其中 xxx 是定时器的标识符。 当我们按下任意键后,程序会取消定时器事件,并输出 "Timer event cancelled"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值