MFC 單文檔應用中,若在 CWinApp 派生類中調用 SetTimer(),則 CFormView 派生類的 OnTimer() 不會被調用。正確做法是在 View 類中通過窗口句柄創建定時器。
CMyApp::InitInstance() 中調用 SetTimer(1, 3000, NULL)。CRView::OnTimer(UINT_PTR nIDEvent) 響應,但無反應。
// 在 CRView 類成員函數中(如 OnInitialUpdate)
void CRView::OnInitialUpdate() {
CFormView::OnInitialUpdate();
// 獲取當前 View 的窗口句柄
HWND hWnd = GetSafeHwnd();
if (hWnd != NULL) {
// 設置定時器:ID=1,間隔 3000ms,無回調函數
UINT_PTR timerId = SetTimer(hWnd, 1, 3000, NULL);
if (timerId == 0) {
TRACE(_T("創建定時器失敗\n"));
}
}
}
// 在 CRView 中處理 WM_TIMER 消息
void CRView::OnTimer(UINT_PTR nIDEvent) {
if (nIDEvent == 1) {
// 定時任務邏輯
TRACE(_T("定時器觸發\n"));
}
CFormView::OnTimer(nIDEvent);
}
// 銷毀定時器(如 OnDestroy)
void CRView::OnDestroy() {
KillTimer(GetSafeHwnd(), 1);
CFormView::OnDestroy();
}
| 錯誤做法 | 正確做法 |
|---|---|
| App 類調用 SetTimer() | View 類調用 SetTimer(hWnd, ...) |
| 無窗口句柄關聯 | 綁定 View 的 HWND |
| 消息路由不到 View | View 窗口進程接收 WM_TIMER |
CCRView MyView;
HWND MyHandle = MyView.GetSafeHwnd();
SetTimer(MyHandle, 1, 3000, NULL);
注意:CCRView MyView 應為已存在的 View 實例指針,而非局部構造對象(否則對象銷毀導致句柄無效)。實際中直接用 this->GetSafeHwnd() 即可。