如何使用多媒体定时器

目前,Windows软件一般使用Timer定时器进行定时。Timer定时器是由应用程序响应定时消息WM_TIMER实现定时。Timer定时器是IBM PC硬件和ROM BIOS构造的定时器的简单扩充。PCROM初始化8253定时器来产生硬件中断08H,而08H中断的频率为18.2Hz,即至少每隔54.925 ms中断一次。此外,这个定时消息的优先权太低,只有在除WM_PAINT外的所有消息被处理完后,才能得到处理。多媒体定时器也是利用系统定时器工作的,但它的工作机理和普通定时器有所不同。首先,多媒体定时器可以按精度要求设置8253T/C0通道的计数初值,使定时器不存在54.945ms的限制;其次,多媒体定时器不依赖于消息机制,而是用函数产生一个独立的线程,在一定的中断次数到达后,直接调用预先设置好的回调函数进行处理,不必等到应用程序的消息队列为空,从而切实保障了定时中断得到实时响应,使其定时精度可达1ms

调用timeGetDevCaps可以获得定时服务参数。

timeGetDevCaps函数的定义如下:

MMRESULT timeGetDevCaps(LPTIMECAPS ptc, UINT cbtc);

调用timeBeginPeriod函数可以设置定时的最小分辨率。

timeBeginPeriod函数的定义如下:

MMRESULT timeBeginPeriod(UINT uPeriod);

调用timeSetEvent设置并启动定时器。

timeSetEvent函数的定义如下:

MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD dwUser, UINT fuEvent);

调用timeKillEvent函数可以取消定时器。

timeKillEvent函数的定义如下:

MMRESULT timeKillEvent(UINT uTimerID);

 

1)创建一个基于对话框的应用程序,名称为Demo

2)在IDD_DEMO_DIALOG对话框资源中添加控件,如表所示。

类型

ID

标题

Edit

IDC_TIME

 

Button

IDC_TEST1

设置定时器

Button

IDC_TEST2

取消定时器

3)创建1个基类为CWinThread的类CTimerThread

4)在TimerThread.h文件中定义宏,代码如下:

#define WM_THREADMSG WM_USER+1

5)在TimerThread.h文件中定义数据结构,代码如下:

typedef struct THREAD_PARAM

{

         HWND hWnd;

         int nTime;

         HANDLE hTimerEvent;

         HANDLE hExitEvent;

}_THREAD_PARAM;

6)在CWinThread类中添加成员变量,代码如下:

public:

         THREAD_PARAM* m_pThreadParam;

7)在CTimerThread类中重载CWinThread::Run函数,代码如下:

// TimerThread.cpp

int CTimerThread::Run()

{       

         while (TRUE)

         {

                   //等待定时事件

                  while (WAIT_TIMEOUT ==

                            WaitForSingleObject(m_pThreadParam->hTimerEvent, 200))

                   {

                            //等待退出事件

                            if (WaitForSingleObject(m_pThreadParam->hExitEvent, 0) == WAIT_OBJECT_0)

                            {

                                     ::AfxEndThread(0);

                            }

                   }

                  m_pThreadParam->nTime += 100;

                   //向主线程窗口发送消息

                  ::PostMessage(m_pThreadParam->hWnd, WM_THREADMSG, 0, 0);

                   //复位定时事件

                  ResetEvent(m_pThreadParam->hTimerEvent);     

         }

}

8)在CDemoDlg类中添加成员变量,代码如下:

// DemoDlg.cpp

private:

         UINT m_nTimerID;

         CTimerThread* m_pTimerThread;

         THREAD_PARAM m_ThreadParam;

9)在CDemoDlg类的构造函数和析构函数中添加如下代码:

// DemoDlg.cpp

CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)

         : CDialog(CDemoDlg::IDD, pParent)

{

         // …

         m_nTimerID = 0;

         m_pTimerThread = NULL;

         m_ThreadParam.nTime = 0;

         m_ThreadParam.hTimerEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

         m_ThreadParam.hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

}

CDemoDlg::~CDemoDlg()

{

         //取消定时器

         if (m_nTimerID != 0)

         {

                  timeKillEvent(m_nTimerID);

         }

         //结束定时线程

         if (m_pTimerThread != NULL)

         {

                   //设置退出事件

                  SetEvent(m_ThreadParam.hExitEvent);

                   //等待定时线程结束

                  ::WaitForSingleObject(m_pTimerThread->m_hThread, INFINITE);

                  delete m_pTimerThread;

                  m_pTimerThread = NULL;

         }

         CloseHandle(m_ThreadParam.hTimerEvent);

         CloseHandle(m_ThreadParam.hExitEvent);

}

10)在CDemoDlg类中为重载CDialog::OnInitDialog函数,代码如下:

// DemoDlg.cpp

BOOL CDemoDlg::OnInitDialog()

{

         CDialog::OnInitDialog();

         // …

         SetDlgItemInt(IDC_TIME, 0);

         return TRUE;

}

11)在CDemoDlg类中为WM_THREADMSG添加消息处理函数,代码如下:

// DemoDlg.cpp

BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)

         //{{AFX_MSG_MAP(CDemoDlg)

         // …

         ON_MESSAGE(WM_THREADMSG, OnMsgFunc)

         //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

LRESULT CDemoDlg::OnMsgFunc()

{

         SetDlgItemInt(IDC_TIME, m_ThreadParam.nTime);

         return 1;

}

12)在CDemoDlg类中为Button控件添加BN_CLICKED消息处理函数,代码如下:

// DemoDlg.cpp

void CDemoDlg::OnTest1()

{

         //取消定时器

         if (m_nTimerID != 0)

         {

                  timeKillEvent(m_nTimerID);

         }

         //结束定时线程

         if (m_pTimerThread != NULL)

         {

                   //设置退出事件

                  SetEvent(m_ThreadParam.hExitEvent);

                   //等待定时线程结束

                  ::WaitForSingleObject(m_pTimerThread->m_hThread, INFINITE);

                  delete m_pTimerThread;

                  m_pTimerThread = NULL;

         }

         m_ThreadParam.hWnd = GetSafeHwnd();

         m_ThreadParam.nTime = 0;

         SetDlgItemInt(IDC_TIME, 0);

         TIMECAPS tc;

         //获得定时器分辨率

         if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)

         {

                  return;

         }

         UINT nResolution = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);

         UINT nInterval = 100;

         if (nInterval < nResolution)

         {

                  nInterval = nResolution;

         }

         //设置定时最小分辨率

         timeBeginPeriod(nResolution);

         //设置定时器

         m_nTimerID = timeSetEvent(nInterval, nResolution,

                  (LPTIMECALLBACK)m_ThreadParam.hTimerEvent,

                  (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);

         //创建定时线程

         m_pTimerThread = (CTimerThread*)AfxBeginThread(RUNTIME_CLASS(CTimerThread),

                  THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);

         m_pTimerThread->m_bAutoDelete = FALSE;

         m_pTimerThread->m_pThreadParam = &m_ThreadParam;

         m_pTimerThread->ResumeThread();

}

void CDemoDlg::OnTest2()

{

         //取消定时器

         if (m_nTimerID != 0)

         {

                  timeKillEvent(m_nTimerID);

         }

         //结束定时线程

         if (m_pTimerThread != NULL)

         {

                   //设置退出事件

                  SetEvent(m_ThreadParam.hExitEvent);

                   //等待定时线程结束

                  ::WaitForSingleObject(m_pTimerThread->m_hThread, INFINITE);

                  delete m_pTimerThread;

                  m_pTimerThread = NULL;

         }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以精确到1毫秒的定时器——多媒体定时器 主要用于数据采集。VB、VC 混合编程! 1、HighResolutionTimer 2、HL_mmTimer2 两者几乎一样,精度高,但都有个问题:一个进程中只能用一个此种控件! mmTimer_source.rar 是 mmTimer 控件的原版。 可以精确到1毫秒的定时器——多媒体定时器 ' *********************************************************************************** ' 功 能:可以精确到1毫秒的定时器——多媒体定时器 ' 特别注意:(一个工程中只能添加一个控件实例!第二个不执行,但不会导致程序崩溃!) ' 使用方法:方法一: ' 1、在窗体上添加此控件。 ' 2、调用函数 Init,设置时间间隔,并开启计时器! ' 3、在 Timer() 事件中添加执行代码。 ' 4、调用函数 Destroy,停止计时器。 ' 方法二: ' 1、在窗体上添加此控件。 ' 2、设置 Interval 属性。 ' 3、设置 Enabled 属性,开启或关闭计时器。 ' 4、在 Timer() 事件中添加执行代码。 ' 作 者:鹤望兰·流 ' 发布日期:2010-05-27 ' 网 站:http://hewanglan.ys168.com ' E - mail:hewanglan34512@163.com ' 依 赖:(HighResolutionTimer.ctx,HighResolutionTimer.dll,MhrtCallBack.bas) ' 更 新: ' * (******* 复制请保留以上信息 *******) ' ************************************************************************************** 本控件采用多媒体定时器包装而成,注意打包时带上"winmm.dll"。 为使VB6能用上它,用VC6封装出DLL,提供API接口,通过发送WM_KEYUP消息到VB6的用户控件触发计时事件! 超强Timer—— 用于需要对时间精确控制或者消息队列很忙的情况 http://blog.csdn.net/godwater8/archive/2007/04/10/1559458.aspx
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、付费专栏及课程。

余额充值