MFC中SetTimer,ON_WM_TIMER和OnTimer的关系和使用
2015-09-15 09:46
176 查看
定时器在VC中的使用频繁,以下讨论定时器的使用方法。
定时器的原型是:
//windows API
函数WINUSERAPI UINT WINAPI SetTimer ( HWND hWnd , UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
hWnd 是欲设置定时器的窗体句柄。定时时间到时,系统会向该窗体发送WM_TIMER消息。
nIDEvent 定时器标识符。在一个窗体内可以使用多个定时器,不同的定时器根据nIDEvent来区分。
uElapse 定时时间,单位是毫秒。
lpTimerFunc 定时器的回调函数。如果该值为NULL,定时时间到时,定时器发送的消息WM_TIMER由窗体映像该消息的函数处理;
否则由回调函数处理,说白一点,回调函数就是取代OnTimer的处理函数。
通常,我们在使用定时器时,只用到三个参数,即
UINT CWnd::SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) );
其实,这个函数只是MFC对API的封装,其实现函数为:
_AFXWIN_INLINE UINT CWnd::SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD))
{
ASSERT(::IsWindow(m_hWnd));
return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer);
}
由此可见,CWnd::SetTimer只是将API函数SetTimer的第一个参数设置成它自己的句柄而已。有了上面的认识,对定时器的使用就清楚了,
下面举例说明定时器的具体使用。
1.打开VC,新建一基于对话框的工程,工程名为Test。在对话框上添加一按钮,将其ID改为IDC_BUTTON_START,Caption改为 Start.
映像该按钮的BN_CLICKED消息,void CTestDlg::OnButtonStart();
2.再在对话框上添加一按钮,ID为ID_BUTTON_STOP,Caption改为Stop,映像消息为void CTestDlg::OnButtonStop();
3.添加一个Lable,ID改为IDC_STATIC_TIME,用于记数,表明定时器函数的执行。
4.映像对话框的WM_TIMER消息,void CTestDlg::OnTimer(UINT nIDEvent);
BEGIN_MESSAGE_MAP(CAssistantDlg, CDialog)
ON_WM_TIMER()
END_MESSAGE_MAP()
以上的定现函数如下所示:
void CTestDlg::OnButtonStart()
{
SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
}
void CTestDlg::OnButtonStop()
{
KillTimer(1); //关闭定时器1。
}
void CTestDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case 1:
static int nTimer=0;
CString strTmp="";
strTmp.Format("Timer: %d",nTimer++);
CWnd *pWnd=GetDlgItem(IDC_STATIC_TIME);
pWnd->SetWindowText(strTmp); 将Lable中设置新值,表明定时器已经工作。
break;
default:
break;
}
CDialog::OnTimer(nIDEvent);
}
回调函数的使用。
如果不想使用窗体的WM_TIMER消息函数处理,可以使用回调函数来取代,读者可以在上面例子的基础上,增加一个回调函数,以证实前面的讨论。
首先,定义一个回调函数,回调函数的定义必须按照如下格式。
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );
我的实现函数如下:
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime )
{
AfxMessageBox("Timer is running!");//定时器时间到,弹出一对话框,表明定时器已经运行。
}
将上面的启动函数稍做修改
void CTestDlg::OnButtonStart()
{
// SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
SetTimer(1,1000,(TIMERPROC)TimerProc);//用回调函数处理,此时对话框的消息处理函数不再处理。
}
感谢原创者的分享!
定时器的原型是:
//windows API
函数WINUSERAPI UINT WINAPI SetTimer ( HWND hWnd , UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
hWnd 是欲设置定时器的窗体句柄。定时时间到时,系统会向该窗体发送WM_TIMER消息。
nIDEvent 定时器标识符。在一个窗体内可以使用多个定时器,不同的定时器根据nIDEvent来区分。
uElapse 定时时间,单位是毫秒。
lpTimerFunc 定时器的回调函数。如果该值为NULL,定时时间到时,定时器发送的消息WM_TIMER由窗体映像该消息的函数处理;
否则由回调函数处理,说白一点,回调函数就是取代OnTimer的处理函数。
通常,我们在使用定时器时,只用到三个参数,即
UINT CWnd::SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) );
其实,这个函数只是MFC对API的封装,其实现函数为:
_AFXWIN_INLINE UINT CWnd::SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD))
{
ASSERT(::IsWindow(m_hWnd));
return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer);
}
由此可见,CWnd::SetTimer只是将API函数SetTimer的第一个参数设置成它自己的句柄而已。有了上面的认识,对定时器的使用就清楚了,
下面举例说明定时器的具体使用。
1.打开VC,新建一基于对话框的工程,工程名为Test。在对话框上添加一按钮,将其ID改为IDC_BUTTON_START,Caption改为 Start.
映像该按钮的BN_CLICKED消息,void CTestDlg::OnButtonStart();
2.再在对话框上添加一按钮,ID为ID_BUTTON_STOP,Caption改为Stop,映像消息为void CTestDlg::OnButtonStop();
3.添加一个Lable,ID改为IDC_STATIC_TIME,用于记数,表明定时器函数的执行。
4.映像对话框的WM_TIMER消息,void CTestDlg::OnTimer(UINT nIDEvent);
BEGIN_MESSAGE_MAP(CAssistantDlg, CDialog)
ON_WM_TIMER()
END_MESSAGE_MAP()
以上的定现函数如下所示:
void CTestDlg::OnButtonStart()
{
SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
}
void CTestDlg::OnButtonStop()
{
KillTimer(1); //关闭定时器1。
}
void CTestDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case 1:
static int nTimer=0;
CString strTmp="";
strTmp.Format("Timer: %d",nTimer++);
CWnd *pWnd=GetDlgItem(IDC_STATIC_TIME);
pWnd->SetWindowText(strTmp); 将Lable中设置新值,表明定时器已经工作。
break;
default:
break;
}
CDialog::OnTimer(nIDEvent);
}
回调函数的使用。
如果不想使用窗体的WM_TIMER消息函数处理,可以使用回调函数来取代,读者可以在上面例子的基础上,增加一个回调函数,以证实前面的讨论。
首先,定义一个回调函数,回调函数的定义必须按照如下格式。
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );
我的实现函数如下:
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime )
{
AfxMessageBox("Timer is running!");//定时器时间到,弹出一对话框,表明定时器已经运行。
}
将上面的启动函数稍做修改
void CTestDlg::OnButtonStart()
{
// SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
SetTimer(1,1000,(TIMERPROC)TimerProc);//用回调函数处理,此时对话框的消息处理函数不再处理。
}
感谢原创者的分享!
相关文章推荐
- Qt 学习之路 :Qt 模块简介
- jquery查询页面表单进行提交
- 三大电信运营商“流量不清零”,何时彻底兑现?
- 加载中动画(gif)
- 推荐!手把手教你使用Git
- Caffe 安装配置(CentOS + 无GPU)
- int数组操作类(不是list,自动扩张的数组)
- C# 操作.ini配置文件
- 解决:busybox编译 fatal error: curses.h: 没有那个文件或目录
- 实战使用Axure设计App,使用WebStorm开发(6) – 迈向后端
- python random模块
- (ping、tennet、ssh、netstat)
- JFinal项目之自动删除日志文件功能
- 此为主博客,会将以前的博客整理到此
- select onchange事件
- web.xml初始化顺序
- HDU 4916 Count on the path
- uboot源码整体框架
- quartus ii 学习使用笔记
- js 剪切板应用clipboardData详细解析