【MFC】基于对话框的键盘响应

VC中键盘事件处理主要是通过对相应的消息的响应,这些事件有如:WM_CHAR、

 

WM_KEYDOWN、WM_KEYUP等他们分别对应OnChar、OnKeyDown、OnKeyUp消息处

 

理函数;当然在有些时候我们也可能需要用到对PreTranslateMessage函数的重载。

 

从这些事件的名称我们可以看出WM_CHAR表示字符事件,WM_KEYDOWN表示键

 

盘的键被按下时事件,而WM_KEYUP则表示键盘的键被放开时的事件;我们在键盘上按

 

下某个键时系统先调用OnKeyDown函数接着调用OnChar函数最后调用OnKeyUp函数;

 

这些消息函数的原形如下:

 

afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);

 

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

 

afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);

 

nChar代表虚拟键,nRepCnt代表重复次数;而对于nFlags则有点麻烦但大多数时候我们不

 

管这个参数,nFlags的具体意义请参考MSDN相关文档。

 

在大多数时候我们只要用到OnChar、OnKeyDown、OnKeyUp这些消息处理函数就够

 

了,但有时候我们会发理这些函数并不会被调用(特别是对话框程序)这时我们就必需去重

 

载PreTranslateMessage函数;些函数的使用也比较简单但在处理组合按键时我们必需用到相

 

键盘消息被拦截而得不到正常响应,其中的关键就是Run函数对消息的预处理。在Run

 

函数中,调用了函数CWinThread::PumpMessage,就是利用这一函数,MFC实现了对消息

 

的分流,使得消息沿着MFC对各种消息规定的路线流动,直到被正确响应。函数PumpMessage调用了函数CWinThread::PreTranslateMessage对消息进行处理,如

 

果该函数不对消息进行处理,则调用API函数TranslateMessage函数将虚拟键消息转换为字

 

符消息并调用DispatchMessage分发消息给窗口处理程序。在对话框中,程序用

 

CWinThread::PreTranslateMessage函数处理了键盘消息,所以对话框程序是否要响应键盘消

 

息,将完全由CWinThread::PreTranslateMessage函数来决定了。

 

在CWnd及其派生类的成员函数PreTranslateMessage函数是一个虚函数,可以通过重

 

载来改变其处理过程。在默认情况下,没有重载这一函数。

 

例子1:

 

在VC6中创建基于对话框的工程,在Class view中找到相应的对话框类单击右键,在右键

 

菜单中选择Add Virtual Fuction...项,然后找到PreTranslateMessage虚函数进行加载。相应的

 

代码中如下:

BOOL CTestDlg::PreTranslateMessage(MSG* pMsg) 

 

{

 

    // TODO: Add your specialized code here and/or call the base class

 

    //判断是否是按键消息

 

    if( pMsg->message == WM_KEYDOWN )

 

    {

 

        MessageBox("有键被按下");

 

        //判断具体键

 

        switch( pMsg->wParam )

 

       

 

          case VK_LEFT://按下左键

 

              MessageBox(_T("左"));

 

              return TRUE;

 

              break; 

 

          case VK_RIGHT://按下右键

 

              MessageBox(_T("右"));

 

              return TRUE;

 

               break;   

          case VK_UP://按下上键

 

              MessageBox(_T("上"));

 

              return TRUE;

 

              break; 

 

         case VK_DOWN://按下下键

 

              MessageBox(_T("下"));

 

              return TRUE;

 

              break; 

 

        default: 

 

              return TRUE;

 

              break; 

 

      }

 

      return CDialog::PreTranslateMessage(pMsg);

 

    }

 

}

///

将return CDialog::PreTranslateMessage(pMsg);放在if里将导致程序无法正常关闭!

最起码应该放到if的外面去。

下面是一个用WASD这几个按键控制滑块的代码:(用→这样的按钮控制时老是出问题)

其中m_X,和m_Y为滑块的控制变量

BOOL CTestDlg::PreTranslateMessage(MSG *pMsg)
{
 if (pMsg->wParam == 'W')
 {
  Y = m_Y.GetPos();
  Y++;
  m_Y.SetPos(Y);
 }
 else if (pMsg->wParam == 'S')
 {
  Y = m_Y.GetPos();
  Y--;
  m_Y.SetPos(Y);
 }
 else if (pMsg->wParam == 'A')
 {
  X = m_X.GetPos();
  X--;
  m_X.SetPos(X);
 }
 else if (pMsg->wParam == 'D')
 {
  X = m_X.GetPos();
  X++;
  m_X.SetPos(X);
 }

 return CDialog::PreTranslateMessage(pMsg);
}

当然也可以分开写:

   1.先添加PreTranslateMessage(pMsg);里面只加入:

     return   CDialog::PreTranslateMessage(pMsg);

     即:
     BOOL CKEYDlg::PreTranslateMessage(MSG *pMsg)
    {
       // TODO: Add your specialized code here and/or call the base class
       return CDialog::PreTranslateMessage(pMsg);
     }

   2.然后添加单独添加WM_KEYDOWN等消息:

   void CKEYDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
   {
      // TODO: Add your message handler code here and/or call default
      if (nChar == VK_SPACE)
      {
        MessageBox("空格键被按下","提示!");
       }
     CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
    }

另附上 虚拟码:

   后面括号的是对应的ASCII码
   ESC键         VK_ESCAPE (27) 
   回车键:      VK_RETURN (13) 
   TAB键:       VK_TAB (9) 
   Caps Lock键: VK_CAPITAL (20) 
   Shift键:     VK_SHIFT ($10) 
   Ctrl键:      VK_CONTROL (17) 
   Alt键:       VK_MENU (18) 
   空格键:      VK_SPACE ($20/32) 
   退格键:      VK_BACK (8) 
   左徽标键:    VK_LWIN (91) 
   右徽标键:    VK_LWIN (92) 
   鼠标右键快捷键:VK_APPS (93)

 

  

    Insert键:   VK_INSERT (45) 
    Home键:     VK_HOME (36) 
    Page Up:    VK_PRIOR (33) 
    PageDown:   VK_NEXT (34) 
    End键:      VK_END (35) 
    Delete键:   VK_DELETE (46)

 

方向键(←): VK_LEFT (37) 
方向键(↑): VK_UP (38) 
方向键(→): VK_RIGHT (39) 
方向键(↓): VK_DOWN (40)

 

F1键: VK_F1 (112) 
F2键: VK_F2 (113) 
F3键: VK_F3 (114) 
F4键: VK_F4 (115) 
F5键: VK_F5 (116) 
F6键: VK_F6 (117) 
F7键: VK_F7 (118) 
F8键: VK_F8 (119) 
F9键: VK_F9 (120) 
F10键: VK_F10 (121) 
F11键: VK_F11 (122) 
F12键: VK_F12 (123)

 

Num Lock键: VK_NUMLOCK (144) 
小键盘0: VK_NUMPAD0 (96) 
小键盘1: VK_NUMPAD0 (97) 
小键盘2: VK_NUMPAD0 (98) 
小键盘3: VK_NUMPAD0 (99) 
小键盘4: VK_NUMPAD0 (100) 
小键盘5: VK_NUMPAD0 (101) 
小键盘6: VK_NUMPAD0 (102) 
小键盘7: VK_NUMPAD0 (103) 
小键盘8: VK_NUMPAD0 (104) 
小键盘9: VK_NUMPAD0 (105) 
小键盘.: VK_DECIMAL (110) 
小键盘*: VK_MULTIPLY (106) 
小键盘+: VK_MULTIPLY (107) 
小键盘-: VK_SUBTRACT (109) 
小键盘/: VK_DIVIDE (111)

 

Pause Break键: VK_PAUSE (19) 
Scroll Lock键: VK_SCROLL (145) 
 
字母的虚拟码直接使用ASCII码即可

另外需要注意:

VK_?? 定义在 winuser.h 中,而对于字母123...,ABC..却没有VK_A,VK_B...

MFC中恰恰没有VK_0 -- VK_9,VK_A --VK_Z ,倒是有VK_NUMPAD0   --VK_NUMPAD9
在delphi,BCB,JAVA中都有。

当然,你可以直接定义,但是打开winuser.h会找到:


所以直接用'A'就行了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值