Windows多媒体定时器(精确到1ms)

MSDN  多媒体地址 :https://msdn.microsoft.com/en-us/library/windows/desktop/dd757634(v=vs.85).aspx

我的经验:我把MSDN上多媒体定时器的相关文档看完了。 就上面的这个 链接才是核心。 


------------------先看看下面的这个(转载别人的)-------------------

一、多媒体定时器的使用

多媒体定时器不依赖消息机制,而是有TimeSetEvent()产生一个独立的线程,在一定的中断次数到达后,直接调用预先设置的回调函数进行处理,而不必等待应用程序的消息队列为空,保证的定时器的实时相应,是一种很理想的高精度定时器,可以实现精度为1ms的定时精度。

1.多媒体定时器的使用

首先要包含MMSystem.h头文件,还要添加以下代码
#pragma comment(lib,"winmm.lib")

启动多媒体定时器原型

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

参数说明: 
uDelay:以毫秒指定时的周期 
Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。 
LpTimeProc:指向一个回调函数,该回调函数包含需要定时执行的代码。 
DwUser:存放用户提供的回调数据。 
FuEvent:指定定时器事件类型: 
TIME_ONESHOT:uDelay毫秒后只产生一次事件。 
TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。

例: 
UINT TimerID = timeSetEvent(1,1(LPTIMECALLBACK)MMTimerProc,(DWORD)this,TIME_PERIODIC);

停止多媒体定时器 
timeKillEvent(TimerID);

多媒体定时器回调函数

void CALLBACK CMMTimerDlg::MMTimerProc(UINT uID,UINT uMsg,DWORD dwUsers,DWORD dw1,DWORD dw2)
{
    CXXX *pDlg = (CMMTimerDlg*)(dwUsers);
    //添加你的代码
}

此函数一定要声明为静态函数

二.普通定时器

开启普通定时器原型 
UINT SetTimer(UINT nIDEvent,UINT nElapse,void ( CALLBACK* lpfnTimer )(HWND, UINT,UINT,DWORD) = NULL )

参数说明: 
nIDEvent:非0值标识Timer的id 。 
nElapse:以毫秒为单位的定时间隔时间 
lpfnTimer 指向定时事件到达时调用的函数的指针,如果为NULL,那么调用WM_TIMER响应函数OnTimer()。

例: 
SetTimer(1,200,NULL); //设置并启动一个时间间隔为200ms的定时器。消息响应函数为OnTimer() 
SetTimer(2,1000, TimerProc ); //设置并启动一个实间间隔为1s的定时器,该定时器的响应函数为TimerProc。

停止定时器 
KillTimer(TimerID); //TimerID为要结束的定时器ID号

普通定时器回调函数

若SetTimer第三个参数为NULL则不需要自己写回调函数,定时器时间到将产生WM_TIMER消息

自己定义回调函数 
例: 
SetTimer(1,1,(TIMERPROC)WMTimerProc);

void CALLBACK CMMTimerDlg::WMTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
    CMMTimerDlg *pDlg = (CMMTimerDlg*)(AfxGetApp()->m_pMainWnd);
   //添加你的代码
}

  先把这些概念 了解下。


问题描述:

          现在用定时器,定时发送数据,精度 越高越好。

           环境:Windows



       拿起了 MFC ,做了个了例子。试试自己捣鼓了半天定时器的结果

     --------------------------------- 我自己封装的------------------------

 1、先看看源码吧。 

        我自己定义了一个类,把定时器封装起来了。方便使用。

       文件名:timer.h

#pragma once
#include "stdafx.h"
#include <Mmsystem.h>
#include <Windows.h>

#pragma comment(lib,"Winmm.lib")


class Timer
{
public:
	Timer();
	~Timer();

	// 创建了,定时器就启动了
	bool Creat(UINT n, UINT period, LPTIMECALLBACK callBack, DWORD dwuser);

	// 停止定时器
	bool Stop();

	// 返回定时器创建标识
	bool GetIsCreateFlag();

private:

	MMRESULT mm;

	// true:定时器创建成功, false, 定时器没有创建
	bool isCreate;
};



       文件名:timer.cpp

#include "stdafx.h"
#include "timer.h"


Timer::Timer()
{
	this->isCreate = false;
}


Timer::~Timer()
{
	
}



// 创建定时器
bool Timer::Creat(UINT n, UINT period,  LPTIMECALLBACK callBack, DWORD dwuser)
{
	this->mm = timeSetEvent(n, period, (LPTIMECALLBACK)callBack, (DWORD)this, TIME_PERIODIC);

	TRACE("\n-----------------定时器创建成功----------------\n");
	this->isCreate = true;

	return true;
}

// 终止定时器
bool Timer::Stop()
{
	if (this->isCreate)
	{
		timeKillEvent(this->mm);
		TRACE("\n-----------------定时器销毁成功----------------");
		return true;
	}

	return false;
}
 

bool Timer::GetIsCreateFlag()
{
	return this->isCreate;
}




    2、使用定时器

           A、界面 ,准备了一个按钮。



      然后,在界面所在对话框头文件中定义了一个回调函数,回调函数要定义成 静态, 原型如下:

	// 定时器回调函数
	static void CALLBACK OnSend(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 );
    参数有点多, 不过,好像都没用到。

          

      接着 定义了一个定时器对象

     Timer *mTimer; 


      源码

	// 定时器回调函数
	static void CALLBACK OnSend(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2 );


private:
	Timer *mTimer;


       B、定时器实现

void CALLBACK CtableDemoDlg::OnSend(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
	AfxMessageBox(L"定时器被调用了");
}


      C、定时器使用就更简单了,在 click按钮事件下:

	// TODO: 在此添加控件通知处理程序代码
	mTimer = new Timer;
	mTimer->Creat(5000, 0, OnSend, NULL);

      D、后来,我又添加了一个按钮,停止定时器用的,停止定时器按钮事件:

	// TODO: 在此添加控件通知处理程序代码
	if (this->mTimer->GetIsCreateFlag())
	{
		if (this->mTimer)
		{
			this->mTimer->Stop();
			delete this->mTimer;
			this->mTimer = NULL;
		}
	}

      

-----------------------  有时,我也忘了-----------------------

  我也会忘了 手动终止定时器。 定义定时器的时,定义为指针,然而没有手动收回申请的内存。 GG 内存泄漏。

 解决方案:

   添加窗体的  WM_Destroy 消息,消息函数体:

void CtableDemoDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO: 在此处添加消息处理程序代码

	if (mTimer != NULL)
	{
		delete mTimer;
		mTimer = NULL;
	}
}

 这样,当窗口销毁时,销毁定时器,就可以了。


  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以精确到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:[email protected] ' 依 赖:(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是定时器的标识符。 需要注意的是,多媒体定时器的精度受到系统负载和硬件性能等因素的影响,因此在实际使用中需要进行测试和调优。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值