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

来源:互联网 发布:生姜怎样治疗脱发 知乎 编辑:程序博客网 时间:2024/06/05 22:40
先看下从网上找到的一篇文章(别急着用):
键盘消息作者:孙文华 时间: 2011-1-6
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 classreturn 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 defaultif (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'就行了!
转载来源:http://blog.sina.com.cn/s/blog_7590da790101285a.html
原创粉丝点击