多媒体定时器(timeSetEvent)及使用pDlg->UpdateData()错误

之前一直使用SetTimer和OnTimer来定时,知道今天碰到了一个应用,运行结果反应SetTimer定时不准,研究了timeSetEvent/timeKillEvent的使用,其可以实现1ms的定时精度。

  1. 使用这两个函数时,需要在头部添加如下语句:
        #include <MMSystem.h>
        #pragma comment(lib, “Winmm.lib”)

  2. timeSetEvent的函数声明如下:
      MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent);
    参数说明:
        uDelay:指定定时的时间,单位是毫秒;
        uResolution:以毫秒指定延时的精度,数值越小,定时器事件的分辨率越高,缺省值为1ms;
        lpTimeProc:指向一个回调函数,该回调函数包含需要定时执行的代码;
        dwUser:存放用户提供的回调数据;
        fuEvent:指定定时器事件的类型:TIME_ONESHOT表示uDelay毫秒后只产生一次事件,TIME_PERIODIC表示每隔uDelay毫秒周期性地产生事件。

  3. 回调函数的形式如下:
    void CALLBACK CXXXDlg::MMTimeProc(UINT uID, UINT uMsg, DWORD dwUsers, DWORD dw1, DWORD dw2)
    {
      CXXXDlg pDlg = (CXXXDlg)(dwUsers);
      //添加你的处理代码
      …
    }
    当回调函数是类里面的函数时,一定要声明为静态函数。

  4. 例子:
    MMRESULT timer_id = timeSetEvent(100, 1, (LPTIMECALLBACK)MMTimeProc, (DWORD)this, TIME_PERIODIC);
      这条语句设定了一个定时器事件,定时精度是1ms,每隔100ms执行一次MMTimeProc指定的回调函数。
      timer_id标识该定时器事件,当不再使用时,可以使用timeKillEvent结束该定时器事件,即timeKillEvent(timer_id)。

  5. 对回调函数的编写需要注意,如果不是类的成员函数,则可以直接这样定义
    void CALLBACK MMTimeProc(UINT uID, UINT uMsg, DWORD dwUsers, DWORD dw1, DWORD dw2)
    {
      //添加你的处理代码
      …
    }
    但是由于在MFC中使用,声明为外部函数会导致访问类成员的困难。因此可以将其定义为类的成员函数,但是需要将其定义为静态成员函数,如此一来,仍旧无法直接访问类的其他成员函数,因为对非静态成员函数的访问需要类对象。
    注意到timeSetEvent的第四个参数,为用户提供的回调数据,因此可以将当前对象的this指针传递给回调函数,然后从回调函数的第三个参数dwUsers解析出来。这样,不论将其声明为外部函数还是类的静态成员函数,均可以对其中的成员数据或函数进行访问。

  6. pDlg->UpdateData()报错
    当我将回调函数声明为类的静态成员函数,并将this指针传递给回调函数时,发现在回调函数内pDlg->UpdateData(TRUE)的执行出现如下图所示错误
    在这里插入图片描述
    针对这一错误,存在两种较为简单的解决方式:

  • 使用control变量或直接获取控件指针对控件的变量进行更新:
    pDlg->m_editCtrl.SetWindowText(pDlg->m_value2);
    pDlg->GetDlgItem(IDC_EDIT2)->SetWindowText(pDlg->m_value2);
  • 最简单的办法,将Debug改为Release即可正常运行。
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows高速定时器是指多媒体定时器,它可以精确控制时间间隔,适用于需要高精度计时的应用程序。多媒体定时器的API函数位于winmm.dll库,可以通过调用这些函数来使用多媒体定时器。 以下是多媒体定时器使用步骤: 1. 引入winmm.dll库。在代码使用以下语句引入: ``` #pragma comment(lib, "winmm.lib") ``` 2. 通过调用timeSetEvent函数创建定时器。该函数的原型为: ``` UINT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent); ``` 其,uDelay表示定时器事件的间隔,单位为毫秒;uResolution表示定时器的最小间隔,单位为毫秒;lpTimeProc是回调函数的指针,当定时器事件发生时会自动调用该函数;dwUser是传递给回调函数的参数;fuEvent定时器的类型,可以选择周期性定时器或单次定时器。 3. 在回调函数编写处理定时器事件的代码。回调函数的原型为: ``` void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); ``` 其,uID是定时器的标识符,uMsg是保留参数,dwUser、dw1、dw2是传递给回调函数的参数。 4. 调用timeKillEvent函数销毁定时器。该函数的原型为: ``` MMRESULT timeKillEvent(UINT uTimerID); ``` 其,uTimerID是定时器的标识符。 需要注意的是,多媒体定时器的精度受到系统负载和硬件性能等因素的影响,因此在实际使用需要进行测试和调优。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值