mfc 关于不响应键盘消息的处理



一:首先介绍键盘消息
系统消息:
    ALT,F1,——F24等,是由系统内部处理的,程序本身就存在,比如F1是帮助键。
    WM_SYSKEYDOWN
    WM_SYSKEYUP
    WM_SYSCHAR
非系统消息:
    是由我们自己加上去的,
    WM_KEYDOWN
    WM_KEYUP
    WM_CHAR

二:然后介绍虚拟键代码
符号形式             十六进制形式        说明
VK_LBUTTON           01             鼠标左键
VK_RBUTTON            02             鼠标右键
VK_CANCEL             03          Control-break 过程
VK_MBUTTON          04                  鼠标中键
VK_BACK                 08           BACKSPACE 键
VK_TAB                    09              TAB 键
VK_CLEAR               0C                CLEAR 键
VK_RETURN              0D            ENTER 键
VK_SHIFT                 10                 SHIFT 键
VK_CONTROL         11                 CTRL 键
VK_MENU                 12                   ALT 键
VK_PAUSE               13                PAUSE 键
VK_CAPITAL             14                CAPS LOCK 键
VK_ESCAPE            1B            ESC 键
VK_SPACE               20                SPACEBAR
VK_PRIOR                21                PAGE UP 键
VK_NEXT                 22                PAGE DOWN 键
VK_END                   23                  END 键
VK_HOME                24             HOME 键
VK_LEFT                 25               LEFT ARROW 键
VK_UP                      26               UP ARROW 键
VK_RIGHT                27               RIGHT ARROW 键
VK_DOWN                28               DOWN ARROW 键
VK_SELECT              29              SELECT 键
VK_EXECUTE          2B                 EXECUTE 键
VK_SNAPSHOT        2C                    PRINT SCREEN键(用于Windows 3.0及以后版本)
VK_INSERT              2D                   INS 键
VK_DELETE            2E                         DEL 键
VK_HELP                 2F                         HELP键

VK_LWIN                 5B                  Left Windows 键 (Microsoft自然键盘)
VK_RWIN                 5C                Right Windows 键 (Microsoft自然键盘)
VK_APPS                5D                  Applications 键 (Microsoft自然键盘)
VK_NUMPAD0         60                 数字小键盘上的 0 键
VK_NUMPAD1         61                    数字小键盘上的 1 键
VK_NUMPAD2         62                 数字小键盘上的 2 键
VK_NUMPAD3         63                 数字小键盘上的 3 键
VK_NUMPAD4         64                 数字小键盘上的 4 键
VK_NUMPAD5         65                   数字小键盘上的 5 键
VK_NUMPAD6        66                数字小键盘上的 6 键
VK_NUMPAD7        67               数字小键盘上的 7 键
VK_NUMPAD8          68               数字小键盘上的 8 键
VK_NUMPAD9         69               数字小键盘上的 9 键
VK_MULTIPLY          6A              Multiply 键
VK_ADD                   6B                 Add键
VK_SEPARATOR           6C           Separator 键
VK_SUBTRACT             6D              Subtract 键
VK_DECIMAL              6E               Decimal 键
VK_DIVIDE               6F               Divide 键
VK_F1                    70               F1 键
VK_F2                    71                  F2 键
VK_F3                    72                   F3 键
VK_F4                    73                   F4 键
VK_F5                     74               F5 键
VK_F6                    75                  F6 键
VK_F7                    76                 F7 键
VK_F8                    77                  F8 键
VK_F9                    78                  F9 键
VK_F10                 79                 F10 键
VK_F11                 7A                 F11 键
VK_F12                 7B                 F12 键
VK_F13                 7C               F13 键
VK_F14                 7D               F14 键
VK_F15                 7 E                   F15 键
VK_F16                 7F                F16 键
VK_F17                80H               F17 键
VK_F18                81H              F18 键
VK_F19                82H               F19 键
VK_F20               83H            F20 键
VK_F21               84H             F21 键
VK_F22                85H             F22 键
VK_F23               86H            F23 键
VK_F24                 87H            F24 键
VK_NUMLOCK         90            NUM LOCK 键
VK_SCROLL         91             SCROLL LOCK 键
VK_ATTN              F6              Attn 键
VK_CRSEL          F7               CrSel 键
VK_EXSEL           F8             ExSel 键
VK_EREOF          F9              Erase EOF 键
VK_PLAY            FA           Play 键
VK_ZOOM           FB             Zoom 键
VK_OEM_CLEAR     FE         Clear 键

三:OnKeyDown不响应的原因:
    只是这个消息在到达窗体之前,已经被它的子控件捕获了,如果将窗体中的所有控件都删除,窗体就会捕获到这个消息,但要注意的是,MFC为了实现在窗体上切换子控件的焦点,已经将 VK_TAB,VK_LEFT,VK_RIGHT,VK_UP,VK_DOWN进行了处理,同时VK_RETURN也被系统捕获用来处理相应的确定事件,所以即使窗体中没控件,这几个键还是无法捕获
    也就是说,一个窗体仅在它没有可视和有效的控件时,才能响应OnKeyDown。

四:具体的解决方法(按键响应方法
    可以调用窗体的PreTranslateMessage函数来实现,具体代码如下:
BOOL CMeetingDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message==WM_KEYDOWN)
{
   switch (pMsg->wParam)
   {
   case VK_F1:
    if (::GetKeyState(VK_CONTROL)<0)
    {
     AfxMessageBox("ss");
    }
    break;
   case VK_F2:
    if (::GetKeyState(VK_CONTROL)<0)
    {
     AfxMessageBox("ss");
    }
    break;
   }
   
}
return CDialog::PreTranslateMessage(pMsg);
}
***********************************************************************************

在MFC(Microsoft Foundation Class)对响应消息进行了封装,

可以通过重载虚函数PreTranslateMessage()对所关心的消息进行截取与响应:

以下对截取与响应键盘 Enter 消息的截取与响应

这是对话框的响应键盘 Enter 消息方式:
BOOL C**Dlg::PreTranslateMessage(MSG* pMsg)
{
   //判断是否为键盘消息
   if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
   {
      //判断是否按下键盘Enter键
      if(pMsg->wParam==VK_RETURN)
      {

          return TRUE;
      }
   }
 return CDialog::PreTranslateMessage(pMsg);
}

这是View视图类响应键盘 Enter 消息的方式:

BOOL C**View::PreTranslateMessage(MSG* pMsg)
{
 if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
 {
  if(pMsg->wParam==VK_RETURN )
  {

        return TRUE;

    }
 }
 return CFormView::PreTranslateMessage(pMsg);
}


 win32 程序中,关于消息有两种传递方式:

1.      MFC 消息, MFC 会把所有的消息一条条放到一个 AFX_MSGMAP_ENTRY 结构中,形成一个数组,该数组存放了所有的消息和与

它们相关的参数。也可以说是放到消息队列里去。

2.      采用 SendMessage() 或其他类似的方式向窗口直接发送的而不经过消息队列的消息。


这两种方式中只有第一种(穿过消息队列的消息)才受 PreTranslateMessage() 影响,

第二种消息并不会理睬 PreTranslateMessage() 的存在。

1)      是否调用 TranslateMessage() 和 DispatchMessage() 是由一个名称为 PreTranslateMessage() 函数的返回值决定的,如果该函数返回

 TRUE ,则不会把该消息分发给窗口函数处理。

2)      传给 PreTranslateMessage() 的消息是未经翻译过的消息,它没有经过 TranslateMessage() 处理。可以在该函数中使用 

(pMsg->wParam==VK_RETURN) 来拦截回车键。

3)      在 WindowProc 里不能处理 WM_Char 消息。( WindowProc 函数见 MFC 消息响应机制一文)

4)      SetWindowText 会发送 WM_Char 给窗口。

5)      PeekMessage 和 GetMessage 的区别:

6)      GetMessage 在没有消息的时候等待消息, cpu 当然低

7)      PeekMessage 没有消息的时候立刻返回,所以 cpu 占用率高。因为游戏不能靠 windows 消息驱动,所以要用 PeekMessage();


另一篇文章中:

            在一个 WIN32 程序中, WINDOWS 会将消息传递给相应的窗口。但是消息不是立即就被传递给相应的窗口,而是会从整个程序最顶层

的窗口传递到下一级窗 口,再传递到下一级窗口,直到传递给目标窗口。在整个过程中,有些消息,在某些特定的情况下,无法默认传递到目

标窗口的。比如用户在 EDIT 控件中按下回 车键, CANCEL 键等,如果 EDIT 窗口之前有对话框窗口,对话框会默认处理回车消息(即响应 

ONOK 函数,然后关闭对话框),然后退出消息传递。所以 EDIT 会收不到。要解决这个问题,可以在 EDIT 窗口之前所有的对话框中重载 

PreTranslateMessage 函数,然后在函数内加上:

if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)     // 如果消息类型为WM_KEYDOWN 并且用户按下的是回车 
  return FALSE;    // 不翻译消息,直接将消息传递下去。具体可查 MSDN 。注意,这里返回值不能为TRUE , TRUE 的意思是翻译消息后退出消

息传递,如此一来虽然也能避开对话框默认处理,但是会退出消息传递,这样 EDIT 控件照样得不到消息。

如此,就可避开对话框默认处理,将消息传递下去。注意:只有对话框才会默认处理按下回车,CANCEL 消息,其他控件窗口则不会,所以在其

他窗口中不必重载 PreTranslateMessage 函数,当然如果重载了也不会错。


附:关于 PreTranslateMessage() 函数的小程序示例:

1 BOOL CSearchuserDlg::PreTranslateMessage(MSG* pMsg) 
  3 {
  5      if (pMsg->message==WM_KEYDOWN)  // 判断是否有按键按下 
  7      { 
  9            switch (pMsg->wParam) 
 11            { 
 13            case VK_DOWN:     // 表示是方向键中的向下的键
 15                 //add handle code here
 17                 break ;
 19            case VK_UP:      // 表示是方向键中的向上的键
 21                 //add handle code here
 23                 break ;
 25            default :
 27                 break ;
 29            }
 31      }
 33 } 
 36 
 37 BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
 38 {
 39      // TODO: Add your specialized code here and/or call the base class 
 41      // 按键相应
 42      if (pMsg->message == WM_KEYDOWN)
 43      {
 44            if (pMsg->wParam == VK_DOWN)
 45            {
 46                 // 向下键按下
 47            }
 48            else if (pMsg->wParam == VK_RIGHT)
 49            {
 50                 // 向右键按下
 51            }
 52            else if (pMsg->wParam == VK_LEFT)
 53           {
 54                 // 向左键按下
 55            }
 56            else if (pMsg->wParam == VK_UP)
 57            {
 58                 // 向上键按下
 59            }
 60            else if (pMsg->wParam == VK_SHIFT)
 61            {
 62                 //VK_LSHIFT 为左 Shift 键按下
 63                 //Shift 键按下
 64            }
 65            else if (pMsg->wParam == VK_CONTROL)
 66            {
 67                 //Ctrl 键按下
 68            }
 69            else if (pMsg->wParam>=VK_NUMPAD0 && pMsg->wParam<=VK_NUMPAD9)
 70            {
 71                 // 小键盘数字键按下
 72            }
 73            else if (pMsg->wParam>=0x30 && pMsg->wParam<=0x39)
 74            {
 75                 // 数字键按下 ( 我记得不能使用 VK_0)
 76            }
 77            else if (pMsg->wParam>=0x41 && pMsg->wParam<=0x5A)
 78            {
 79                 // 键盘字母键按下 ( 我记得不能使用 VK_A)
 80            }
 81            else if (pMsg->wParam == VK_BACK)
 82            {
 83                 // 退格键按下
 84            }
 85            else if (pMsg->wParam == VK_DELETE)
 86            {
 87                 // 删除键按下
 88            }
 89            else if (pMsg->wParam == VK_F1)
 90            {
 91                 //F1 键按下
 92            }
 93 
 94            //return true;  // 使消息不再进行处理
 95      }
 96 
 97      if (pMsg->message == WM_KEYUP)
 98      {
 99            if (pMsg->wParam == VK_SHIFT)
100            {
101                 //Shift 键弹起
102            }
103            else if (pMsg->wParam == VK_CONTROL)
104            {
105                 //Ctrl 键弹起
106            }
107            //return true;  // 使消息不再进行处理
108      }
109 
110      return CDialog::PreTranslateMessage(pMsg);
111 }
112 
113 // 同时按下 ctrl 键
114 BOOL   CDemo_DevStudioView::PreTranslateMessage(MSG*   pMsg)   // 根据键盘上的按键对图形进行相应的操作  
116 
117      if (pMsg->message==256)   //   256 有键按下, 46   DEL 键  
118      { 
119            switch (pMsg->wParam)   
120            { 
121                 /// 向左键被按下    
122            case    37
123                 { 
124                      // 同时按下了 CTRL 键  
125                      if (::GetKeyState(VK_CONTROL)       <       0)       
126                      {       
127                      } 
128                 } 
129            } 
130      }
131 }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值