MFC——12.話框中對鍵盤消息的響應處理&&如何響應wm_char消息

本文爲轉載文章,轉載地址:http://blog.sina.com.cn/s/blog_a9fa057b0101gz1p.html
今天在寫一個小程序的時候,發現在對話框對應的類裏添加鍵盤字符消息,寫了消息響應函數,但沒有反應,查了後發現這篇文章解決了問題。

       創建一個基於對話框的程序,結果發現對於不能直接響應鍵盤按鍵的消息。原來,在MFC中,對話框程序在完成程序的初始化後,就在程序主線程中,調用CWinThread::Run函數。在該函數中,首先調用API函數PeekMessage,而函數PeekMessage檢查線程消息隊列,如果消息存在,就將該消息放於指定的MSG結構中,以後的消息處理都將針對這一MSG結構對象。捕獲消息後,該函數將捕獲的消息進行預處理,然後再將消息傳遞給相應的窗口處理函數。

       鍵盤消息被攔截而得不到正常響應,其中的關鍵就是Run函數對消息的預處理。在Run函數中,調用了函數CWinThread::PumpMessage,就是利用這一函數,MFC實現了對消息的分流,使得消息沿着MFC對各種消息規定的路線流動,直到被正確響應。

       函數PumpMessage調用了函數CWinThread::PreTranslateMessage對消息進行處理,如果該函數不對消息進行處理,則調用API函數TranslateMessage函數將虛擬鍵消息轉換爲字符消息並調用DispatchMessage分發消息給窗口處理程序。在對話框中,程序用CWinThread::PreTranslateMessage函數處理了鍵盤消息,所以對話框程序是否要響應鍵盤消息,將完全由CWinThread::PreTranslateMessage函數來決定了。

       在CWnd及其派生類的成員函數PreTranslateMessage函數是一個虛函數,可以通過重載來改變其處理過程。在默認情況下,沒有重載這一函數。

例子如下,在VC6的Class view中找到相應的對話框類單擊右鍵,在右鍵菜單中選擇Add Virtual Fuction...項,然後找到PreTranslateMessage虛函數進行加載。

 BOOL CKeyinTstDlg::PreTranslateMessage(MSG* pMsg)    //CKeyinTstDlg我爲自己創建的對話框類
{
 // TODO: Add your specialized code here and/or call the base class
	if(pMsg->message == WM_KEYDOWN) 
	{ 
		MessageBox(L"有鍵被按下");
	}
 	 return CDialog::PreTranslateMessage(pMsg);
}

如何響應wm_char消息
創建一個MFC Dialog 的Porject,爲了截獲鍵盤擊鍵的值,需要用到WM_CHAR消息。但在Project中添加該消息後會發現,程序無法響應該消息。即擊鍵後程序並沒有執行到該消息對應的函數處。參考MSDN對該消息的描述:
This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.
 
關鍵的意思是要執行WM_CHAR消息,程序焦點必須在主窗口上。但不幸的是,程序運行以後,焦點在按鈕上。
BOOL CKeyinTstDlg::PreTranslateMessage(MSG* pMsg)    //CKeyinTstDlg我爲自己創建的對話框類
{
 // TODO: Add your specialized code here and/or call the base class
方式是使用PreTranslateMessage消息,進行處理,將焦點設置到主窗口上。具體代碼如下:
if ( pMsg->message == WM_CHAR)  
 {  
  pMsg->hwnd = m_hWnd; 
  return FALSE;
 }  
 return CDialog::PreTranslateMessage(pMsg);
}
然後再OnChar(nChar, nRepCnt, nFlags)中添加對應消息
void Ctest4Dlg::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)//nChar 爲對應按鍵的asc碼值
{
      if (nChar==0xD)
{
dd="";
aa.SetWindowText(dd);
}
CString ss;
ss.Format(L"%c",nChar);
dd=dd+ss;
aa.SetWindowText(dd);
CDialog::OnChar(nChar, nRepCnt, nFlags);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章