一、设置计时器
SetTimer:
函数原型:
UINT_PTR SetTimer(
UINT_PTR nIDEvent,//计时器标识符
UINT nElapse,//超时间隔,每nElapse毫秒发送一次WM_TIMER消息
void (CALLBACK* lpfnTimer //指定WM_TIMER消息的回调,在本例中此函数为NULL,让默认OnTimer来处理计时器消息
)(HWND,
UINT,
UINT_PTR,
DWORD
)
);
销毁计时器 :
BOOL KillTimer(
UINT_PTR nIDEvent
);
或:
BOOL WINAPI KillTimer(第一个为MFC封装后的KillTimer.第二个为WINAPI函数
_In_opt_ HWND hWnd,//响应计时器的窗口句柄
_In_ UINT_PTR uIDEvent//计时器ID
);
在使用第二个WINAPI函数 KillTimer需指定设置计时器的窗口.如:
::KillTimer(hMyWnd,EVENT_TIMER_ID);
在不同窗口类之间传递计时器消息时注意事项:
如果指定窗口为空,则会抛出异常.
示例代码:
首选,建立一个对话框工程,工程名为 MyTimer,主对话框类为 CMyTimerDlg再添加一个对话框资源,创建类 CMyChildTimerDlg
在子窗口中创建计时器:
//mychildtimerdlg.cpp
BEGIN_MESSAGE_MAP(CMyChildTimerDlg, CDialogEx)
ON_WM_TIMER()
END_MESSAGE_MAP()
BOOL CMyChildTimerDlg::OnInitDialog()
{
//创建计时器
SetTimer(EVENT_ON_TIMER, 1000, NULL);//假设已全局定义#define EVENT_ON_TIMER 2
CDialogEx::OnInitDialog();
}
//OnTimer 计时器消息
void CMyChildTimerDlg::OnTimer(UINT_PTR nIDEvent)
{//响应计时器,发送消息给父窗口
::PostMessage(GetParent()->GetSafeHwnd(),
ON_WM_MYTIMER, (WPARAM)this, 0);
CDialogEx::OnTimer(nIDEvent);
}
在父窗口中响应计时器发来的消息:
头文件中:
//mytimerdlg.h
#include "MyChildTimerDlg.h"
public:
CMyChildTimerDlg* ChildTimer;
afx_msg LRESULT OnChildTimer(WPARAM wParam, LPARAM lParam);
实现文件:
//mytimerdlg.cpp
BEGIN_MESSAGE_MAP(CMyTimerDlg, CDialogEx)
ON_MESSAGE(ON_WM_MYTIMER,&CMyTimerDlg::OnChildTimer)//假设已定义消息ON_WM_MYTIMER
END_MESSAGE_MAP()
LRESULT CMyTimerDlg::OnChildTimer(WPARAM wParam, LPARAM lParam)
{
CMyChildTimerDlg* childTimer = (CMyChildTimerDlg*)wParam;
CMyChildTimerDlg* childTimer2 = (CMyChildTimerDlg*)lParam;//Error,Window is NULL
childTimer->KillTimer(EVENT_ON_TIMER);//OK,Timer will Kill;
childTimer2->KillTimer(EVENT_ON_TIMER);//Error, WINDOW is NULL;
}
当程序运行至
chileTimer2->KillTimer(EVENT_ON_TIMER);
出错,
然后我们调试代码.当代码运行至childTimer2->KillTimer(EVENT_ON_TIMER)时,抛出异常:
中断程序,查看抛出异常的代码:
//afxwin2.inl
_AFXWIN_INLINE BOOL CWnd::KillTimer(UINT_PTR nIDEvent)
{ ASSERT(::IsWindow(m_hWnd)); return ::KillTimer(m_hWnd, nIDEvent); }
这里有一处断言,判断当前窗口是否存在.很时显,我们传过来的lParam是0,当然,窗口也就是NULL了.
另外,如果使用WIN API函数 ::KillTimer,虽然窗口为NULL不会抛出异常,但是相应的计时器也无法删除.