VC++ 使用媒体定时器的例子与源码

时间:2022-10-16 08:53:58

VC++默认的定时器,好像精度不大,秒内的不错,但是如果精确到毫秒(ms),不行,如果使用媒体定时器,multimedia timer,则效果显著,基本上精确到毫秒吧,一般的10ms之类的延时,应该可以保证了。

       如何使用呢?网上有例子,但没有完整的,大部分只是介绍,因此我根据网上的代码实现了一下,使用MFC实现,可以在下面的链接下载下来学习与研究。

       可能通过MSDN找到操作媒体定时器(multimedia timer)的相关介绍,主要的操作函数:

(1)timeSetEvent设置定时器(配置并开启)

(2)timeKillEvent关闭定时器

(3)CALLBACK TimerCallBack也可回调函数,(定时器中断了,要执行的函数),名字可以随便起,只是格式上,要符合标准的格式。

(4)OnMMTimer 具体的实现函数:网上是定义为虚函数,然后重写,这里我觉得随便取个名字应该可以,就是用定时器干什么,延时到了,用户要实现什么功能,可以写在这里。上面第三个函数就调用这个函数进行用户程序的实现。


(1)首先工程中要加入头文件:

#include "windows.h"
#include "Mmsystem.h"

(2)设置工程选项:加入Winmm.lib 库,这是使用媒体定时器的库。


界面如下:


VC++ 使用媒体定时器的例子与源码



对话框类的成员函数与成员变量:

public:
UINT m_ms;//毫秒,注意在构造函数里初始化为0
UINT m_timerId;
UINT m_s;
UINT m_m;
UINT m_h;
virtual void OnMMTimer();//声明要回调的成员方法
void TimerCtrl(const bool bEn);//定时器打开与关闭
int i;
MMRESULT TimerID;//媒体定时器的ID,标识


void CTimeSetEvent_V1Dlg::OnBtnTimerStart() 
{
// TODO: Add your control notification handler code here
TimerCtrl(TRUE);
GetDlgItem(IDC_BTN_TIMER_START)->EnableWindow(FALSE);
GetDlgItem(IDC_BTN_TIMER_STOP)->EnableWindow(TRUE);
}

void CTimeSetEvent_V1Dlg::OnBtnTimerStop()
{
// TODO: Add your control notification handler code here
TimerCtrl(FALSE);
GetDlgItem(IDC_BTN_TIMER_START)->EnableWindow(TRUE);
GetDlgItem(IDC_BTN_TIMER_STOP)->EnableWindow(FALSE);
}

void CTimeSetEvent_V1Dlg::OnMMTimer()
{
CString str = "";
m_ms++;
str.Format("%ld",m_ms);
str+="\r\n";
SetDlgItemTextA(IDC_STATIC_MS,str);
CEdit *pEt = (CEdit *)GetDlgItem(IDC_EDIT_HIST);
int nLen=pEt->GetWindowTextLength();
pEt->SetSel(nLen,nLen);
pEt->ReplaceSel(str);
//GetDlgItem(IDC_EDIT_HIST)->
}

void CTimeSetEvent_V1Dlg::TimerCtrl(const bool bEn)
{
if (bEn)
{
m_h = m_m = m_s = 0;
m_timerId = timeSetEvent(1,1,&TimerCallBack,(DWORD)this,TIME_PERIODIC);
}
else
timeKillEvent(m_timerId);
}

void CTimeSetEvent_V1Dlg::OnOK()
{
// TODO: Add extra validation here
GetDlgItem(IDC_EDIT_HIST)->SetWindowText("");
m_ms=0;
//CDialog::OnOK();
}

void CTimeSetEvent_V1Dlg::OnCancel()
{
// TODO: Add extra cleanup here

CDialog::OnCancel();
}



static void CALLBACK TimerCallBack(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CTimeSetEvent_V1Dlg * pThis=(CTimeSetEvent_V1Dlg *)dwUser;//由this指针获得实例的指针

pThis->OnMMTimer(); //调用要回调的成员方法
}

/////////////////////////////////////////////////////////////////////////////
// CTimeSetEvent_V1Dlg dialog

CTimeSetEvent_V1Dlg::CTimeSetEvent_V1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CTimeSetEvent_V1Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTimeSetEvent_V1Dlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_ms=0;
m_s=0;
m_m=0;
m_h=0;
}



       以上为主要的函数实现功能。

目前只是打印出数字来,证明定时器中断可以用,当然,如果设置什么数据发送,如1S中发送100次或是200次,也可以加入。


VC6工程下载:


点击打开链接