一:首先介绍键盘消息
系统消息:
非系统消息:
二:然后介绍虚拟键代码
符号形式
VK_LBUTTON
VK_RBUTTON
VK_CANCEL
VK_MBUTTON
VK_BACK
VK_TAB
VK_CLEAR
VK_RETURN
VK_SHIFT
VK_CONTROL
VK_MENU
VK_PAUSE
VK_CAPITAL
VK_ESCAPE
VK_SPACE
VK_PRIOR
VK_NEXT
VK_END
VK_HOME
VK_LEFT
VK_UP
VK_RIGHT
VK_DOWN
VK_SELECT
VK_EXECUTE
VK_SNAPSHOT
VK_INSERT
VK_DELETE
VK_HELP
VK_LWIN
VK_RWIN
VK_APPS
VK_NUMPAD0
VK_NUMPAD1
VK_NUMPAD2
VK_NUMPAD3
VK_NUMPAD4
VK_NUMPAD5
VK_NUMPAD6
VK_NUMPAD7
VK_NUMPAD8
VK_NUMPAD9
VK_MULTIPLY
VK_ADD
VK_SEPARATOR
VK_SUBTRACT
VK_DECIMAL
VK_DIVIDE
VK_F1
VK_F2
VK_F3
VK_F4
VK_F5
VK_F6
VK_F7
VK_F8
VK_F9
VK_F10
VK_F11
VK_F12
VK_F13
VK_F14
VK_F15
VK_F16
VK_F17
VK_F18
VK_F19
VK_F20
VK_F21
VK_F22
VK_F23
VK_F24
VK_NUMLOCK
VK_SCROLL
VK_ATTN
VK_CRSEL
VK_EXSEL
VK_EREOF
VK_PLAY
VK_ZOOM
VK_OEM_CLEAR
三:OnKeyDown不响应的原因:
四:具体的解决方法(按键响应方法)
BOOL CMeetingDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message==WM_KEYDOWN)
{
}
return CDialog::PreTranslateMessage(pMsg);
}
***********************************************************************************
在MFC(Microsoft Foundation Class)对响应消息进行了封装,
可以通过重载虚函数PreTranslateMessage()对所关心的消息进行截取与响应:
以下对截取与响应键盘 Enter 消息的截取与响应
这是对话框的响应键盘 Enter 消息方式:
BOOL C**Dlg::PreTranslateMessage(MSG* pMsg)
{
}
这是View视图类响应键盘 Enter 消息的方式:
BOOL C**View::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
{
if(pMsg->wParam==VK_RETURN )
{
}
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 }