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;
}
}
这样,当窗口销毁时,销毁定时器,就可以了。