(1)現象
在MFC的對話框中,映射了WM_CHAR和WM_KEYDOWN消息響應函數后,還是不能響應OnKeyDown和OnChar。
(2)原因
因為MFC在進行設計的時候,這兩個消息被對話框上的控件截獲了,不能到達這兩個消息響應函數,對於OnKeyDown來說,只要把對話框
上的控件都刪除了,就可以接收到WM_KEYDOWN消息,但是還是接收不到WM_CHAR消息。
(3)解決
方法1:重載PreTranslateMessage這個虛函數;在里面加上SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);這一句后,對話
框的OnKeyDown和OnChar函數就生效了。
方法2:在PreTranslateMessage虛函數里直接處理WM_KEYDOWN或WM_CHAR。
eg:對話框屏蔽esc鍵
BOOL Cmfc_testDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加專用代碼和/或調用基類
if(pMsg->message == WM_KEYDOWN)
{
if(pMsg->wParam == VK_ESCAPE)
return TRUE;
}
return CDialogEx::PreTranslateMessage(pMsg);
}
(4)執行順序
三個消息的執行順序為WM_KEYDOWN、WM_CHAR、WM_KEYUP
(5)關於PreTranslateMessage()函數
PreTranslateMessage是消息在送給TranslateMessage函數之前被調用的,絕大多數窗口的消息都要通過這里,比較常用,當你需要在
MFC之前處理某些消息時,常常要在這里添加代碼。通過重載這個函數,我們可以改變MFC的消息控制流程,甚至可以作一個全新的控制流
出來。
前面說了絕大多數窗口的消息都可以通過這個虛函數進行控制,這個絕大數其實是只有穿過消息隊列的消息才受PreTranslateMessage
()影響,采用SendMessage()或其他類似的方式向窗口直接發送的而不經過消息隊列的消息根本不會理睬PreTranslateMessage()的存在,
故切記SendMessage 發送的消息是不能用PreTranslate來截取的,應該重寫WindowProc窗口過程來響應消息!
(6)SendMessage()和PostMessage()
SendMessage函數發送的消息會直接發送到窗口過程而不經過消息隊列,且直到消息處理完成后,SendMessage才返回。函數返回值指定
消息處理的結果,依賴於所發送的消息。
PostMessage函數將一個消息寄送到指定窗口的消息隊列里,不等待線程處理消息就立刻返回。函數執行成功返回TRUE,否則返回
FALSE。
LRESULT WINAPI SendMessage(
HWND hWnd, //窗口句柄
UINT Msg, //消息值
WPARAM wParam,//消息附加信息
LPARAM lParam //消息附加信息
);
BOOL WINAPI PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
(6)對話框特殊按鍵消息的處理
默認情況下對話框響應Enter鍵的處理是調用基類的OnOK()函數,Esc鍵會調用基類的OnCancel()函數,這兩個函數都是虛函數,故要
對Enter或Esc鍵做相應處理的話可以重寫這兩個函數。
單擊對話框標題欄上的關閉按鈕時會先后產生WM_CLOSE消息,故需要對標題欄關閉按鈕按下做處理的時候可以在WM_CLOSE消息的消息
響應函數中進行。
原文:http://blog.csdn.net/wang_cong0214/article/details/8280324