MFC之计时器
前言
最近公司需要有一个关于定时执行某项操作的需求,所以想到了利用MFC类库中的窗口类计时器
CWnd::SetTimer
进行计时,从而实现定时执行操作的功能。由于之前没使用过该函数,因此特地寻找资料,学习该函数的用法,并在此记录。
函数说明
CWnd::SetTimer
函数名:
CWnd::SetTimer
函数原型:
UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer) (HWND, UINT, UINT, DWORD) );
概述
这个函数设置一个系统定时器。指定了一个定时值,每当发生超时,则系统就向设置定时器的应用程序的消息队列发送一个WM_TIMER消息,或者将消息传递给应用程序定义的TimerProc回调函数
返回值:如果函数成功,则返回定时器的标示符;如果函数失败,返回0
参数说明:
nIDEvent 定时器标示符,实际上函数成功返回的就是这个值,类型为无符号整型
unsigned int
nElapse 指定了定时值,单位为毫秒。类型为无符号整型
unsigned int
,每当经过的时间到达了这个定时时长时,函数会发送WM_TIMER消息,进行后续处理lpfnTimer 应用程序的回调函数的地址。用来处理当计时器时间到了后,程序需要进行的操作。如果参数为NULL,则函数发送的WM_TIMER消息会被入消息队列中,用CWnd对象处理,触发
CWnd::OnTimer
CWnd::OnTimer
函数名:
CWnd::OnTimer
函数原型:
afx_msg void OnTimer( UINT nIDEvent );
概述:
当SetTimer的回调函数被定位NULL时,当设定的时间到达后,会调用这个函数对WM_TIMER进行消息进行处理。
参数说明:
- nIDEvent 定时器标示符
CWnd::KillTimer
函数名:
CWnd::KillTimer
函数原型:
BOOL KillTimer( int nIDEvent );
概述:
销毁以前调用SetTimer创建的用nIDEvent标识的定时器事件。任何与此定时器有关的未处理的WM_TIMER消息都从消息队列中清除。
返回值:如果销毁成功,返回非0值,如果找不到指定标识符的定时器时间,则返回0
参数说明:
- nIDEvent 定时器标示符,用于传递SetTimer创建的定时器标示符
使用函数
函数的使用其实挺简单的,主要有以下几个步骤:
创建定时器事件
接收定时器传来的消息
编写执行的操作
销毁定时器
创建定时器事件
void CSetTimerDlg::OnOK()
{
// 每2秒执行一次
SetTimer(1, 2000, NULL);
}
此处创建了一个MFC应用,选择的是基本对话框来进行定时器示例。
接收定时器传来的消息
使用建立类向导,为窗口类CSetTimerDlg绑定消息WM_TIMER,并进行消息映射到OnTimer
编写需要执行的操作
void CSetTimerDlg::OnTimer(UINT nIDEvent)
{
// 接收WM_TIMER消息
MessageBox("已经过了2秒啦");
}
此时,定时器已经可以基本使用,当我们将程序编译后执行,点击“确定”按钮,等待2秒后,窗口将弹出一个提示框:
此时,程序将每隔约2秒就弹出一个提示框,说明定时器已经生效,并持续执行。
有时候,我们可能会在程序中创建多个定时器事件,每个定时器事件的标示符都不同,此时,我们可以通过判断WM_TIMER消息传递的定时器标示符来判断到底是哪个定时器事件:
void CSetTimerDlg::OnTimer(UINT nIDEvent)
{
// 接收WM_TIMER消息
if ( nIDEvent == 1 )
{
MessageBox("已经过了2秒啦");
}
else if ( nIDEvent == 2 )
{
MessageBox("这是第二个定时器");
}
}
然而有时候我们只需要定时执行一次或者满足一定条件时就停止执行,因此,我们还需要销毁定时器。
销毁定时器
定时器的销毁只需要在函数体中调用KillTimer函数,并传入定时器标识符即可。
void CSetTimerDlg::OnTimer(UINT nIDEvent)
{
// 接收WM_TIMER消息
MessageBox("已经过了2秒啦");
// 销毁定时器
KillTimer( nIDEvent );
}
在该例中,创建定时器的时候,标示符为1,因此参数为1。
结束
基本的定时器用法就是如上用法,不过需要特别注意的是:
定时器是有限的全局资源;对于应用程序来说,检查SetTimer返回的值以确定定时器是否可用是很重要的。
定时器发送的WM_TIMER在消息队列中,优先级非常低,如果此时有优先级高的消息进入消息队列,那么定时器所发送的消息将被滞后,这样,对于定时时间精确要求特别高的应用来说,使用默认的OnTimer处理消息是不合适的,应该使用回调函数单独处理,而不是让定时器向消息队列中发送WM_TIMER消息