关于对话框不能响应OnKeyDown和OnChar函数的一些说明

时间:2023-03-09 22:32:33
关于对话框不能响应OnKeyDown和OnChar函数的一些说明

(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.****.net/wang_cong0214/article/details/8280324