MFC——12.话框中对键盘消息的响应处理&&如何响应wm_char消息

来源:互联网 发布:怎么举报淘宝卖家店铺 编辑:程序博客网 时间:2024/04/29 17:44
本文为转载文章,转载地址: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 classif(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);}


1 0
原创粉丝点击