2013-10-07 98 views
1

我在VS2010中創建了一個基於MFC對話框的應用程序,並希望添加計時器以每3秒更新一次圖片控制器。但OnTimer方法從未起作用。在MFC中不工作的OnTimer方法

我已經使用類嚮導添加WM_TIMER到消息隊列,這原來是如下:

BEGIN_MESSAGE_MAP(CxxxxDlg, CDialogEx) 
    ON_WM_PAINT() 
    ON_BN_CLICKED(IDOK, &CxxxxDlg::OnBnClickedOK) 
    ON_WM_TIMER() 
END_MESSAGE_MAP() 

在xxxxDlg.cpp,我把SetTimer的方法在OnInitDialog:

BOOL CxxxxDlg::OnInitDialog() 
{ 
    CDialog::OnInitDialog(); 
    SetIcon(m_hIcon, TRUE); 
    SetIcon(m_hIcon, TRUE); 

    _imageCounter = 1; 
    _isMale = 3; 
    _testNum = 0; 

    SetTimer(123, 2000, NULL); 

    bFullScreen = false; 
    OnFullShow(); 
    updateImages(); 
    UpdateData(); 

    return TRUE; 
} 

public: 
    afx_msg void OnTimer(UINT_PTR nIDEvent); 

當運行該應用程序,的SetTimer換貨政...:

計時器觸發方法在xxxxdlv.h declard 123.所以一切都應該在這裏。 但程序從未到達我在OnTimer方法的第一行中設置的斷點!

然後我又寫了一個hello world項目只測試了這個定時器。我以完全相同的方式設置了計時器,並且運行良好。

於是我想到了OnFullShow()方法可能是問題。此方法用於將窗口更改爲全屏模式。我評論這一行,但仍然OnTimer從未工作。

我有檢查問題here。但它沒有幫助。

有誰知道在哪裏的問題從何而來?謝謝!

PS。我確實收到了一些內存泄漏的警告。這是否重要?

+0

難道你'WM_PAINT'功能以某種方式循環,從而使'WM_TIMER'消息沒有得到處理? [嘗試註釋掉你的繪畫函數來檢查] –

+1

'WM_TIMER'是一個低優先級的消息(如'WM_PAINT'和'WM_MOUSEMOVE')。只有當消息隊列爲空並且沒有無效的窗口區域並且沒有鼠標輸入時纔會生成。如果你沒有滿足這兩個條件中的任何一個,即使定時器安裝正確,你也永遠不會得到'WM_TIMER'。 – IInspectable

+0

@EdwardClements我評論這一行,但問題仍然存在。謝謝。 – thundertrick

回答

1

感謝@IInspectable。我找到了技術支持here。它充分解釋了原因,並告訴一個解決方案:

// Rewrite PreTranslateMessage method 
BOOL CMyApp::PreTranslateMessage(MSG *pMsg) 
{ 
    // If this is a timer callback message let it pass on through to the 
    // DispatchMessage call. 
    if((pMsg->message==WM_TIMER) && (pMsg->hwnd==NULL)) 
     return FALSE; 
    ... 
    // The rest of your PreTranslateMessage goes here. 
    ... 

    return CWinApp::PreTranslateMessage(pMsg); 
} 

此解決方案不能解決我的問題,但給了我一個提示。應該重寫PreTranslateMessage方法,讓WM_TIMER傳遞給DispatchMessage調用。 但是,如果你正在使用PreTranslateMessage處理其他消息WM_KEYDOWN例如,上述解決方案可能無法正常工作。這似乎是一個關於優先事項的問題。最後,我用switch代替if解決它:

// Rewrite PreTranslateMessage method 
BOOL CMyApp::PreTranslateMessage(MSG *pMsg) 
{ 
    // If this is a timer callback message let it pass on through to the 
    // DispatchMessage call. 
    switch(pMsg->message) 
    { 
    case WM_KEYDOWN: // your codes 
    case WM_TIMER: return false; 
    ... 
    } 
    ... 
    // The rest of your PreTranslateMessage goes here. 
    ... 

    return CWinApp::PreTranslateMessage(pMsg); 
} 

我希望這將幫助任何人誰也有類似的問題。

PS。 pMsg->hwnd==NULL已在switch中刪除,我不確定它是否安全。