键盘消息

键盘以消息的形式传递给程序的窗口过程。

默认情况下,一些系统功能键 (如:Alt, Ctrl) 的消息由 DefWindowProc() 处理。

接受到键盘事件的窗口称为有输入焦点的窗口。具有输入焦点的窗口要么是活动窗口,要么是活动窗口的子孙窗口。

活动窗口总是最上层的窗口。

窗口通过捕获 WM_SETFOCUS 和 WM_KILLFOCUS 消息来确定自己的窗口是否具有输入焦点。

 

当用户按下和释放键盘上的一个键时,Windows 和 键盘设备驱动程序 将硬件扫描码转换为格式化后的消息。

但是这些消息并不立即放入应用程序消息队列,而是由 Windows 先把这些消息存储在系统消息队列中

系统消息队列是一个单独的消息队列,它被 Windows 用来初步存储用户从键盘和鼠标输入的消息。

仅当 Windows 应用程序完成了对前一个用户输入消息的处理后,Windows 才从系统消息队列中取出下一条消息,

并把它放入应用程序消息队列。

(即先把消息存储在系统消息队列里,再把它们发送到应用程序消息队列)

原因是需要同步,被期望接受键盘输入的窗口是具有活动焦点的窗口。

用户输入的速度可能快于应用程序能处理的击键动作,而一个特殊的击键可能会使焦点从一个窗口转换到另一个窗口,

后续的击键也应该跟着到了另一个窗口。

 

当用户按下一个键时,Windows 将 WM_KEYDOWN 或 WM_SYSKEYDOWN 消息放入具有输入焦点的窗口的消息队列中。

当该键被释放时,Windows 把 WM_KEYUP 或 WM_SYSKEYUP 消息放入相应的消息队列中。

  键按下 键释放
非系统击键 WM_KEYDOWN WM_KEYUP
系统击键 WM_SYSKEYDOWN WM_SYSKEYUP

通常键按下消息和释放消息时成对出现的。但是如果你按下一个键不放时,则被认为发生了一次连续按键(自动重复)行为。

Windows 将发送给窗口过程一连串的 WM_KEYDOWN 或 WM_SYSKEYDOWN 消息。

当此键最终被释放时,Windows 发送给窗口过程一个 WM_KEYUP 或 WM_SYSKEYUP 消息。

像所有消息队列一样,击键消息是可被实时追踪的。你可调用 GetMessageTime(),得到键被按下或释放的相对时间。

 

WM_SYSKEYDOWN 和 WM_SYSKEYUP 中的 “SYS" 代表系统,它表明该击键对 Windows 比对 Windows 应用程序更加重要。

当输入键 和 Alt 键组合时通常产生的是 WM_SYSKEYDOWN 和 WM_SYSKEYUP 消息。

 

对 WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP 这四类击键消息,

这些消息存储在 wParam 中,wParam 是虚拟键代码,用于标识哪个键被按下或被释放。

而 lParam 包含属于本次击键的一些其他数据。

 

你经常使用的大多数虚拟键代码命名是这样的: VK_***。

下表列出了这些虚拟键代码的名称和数值:

十进制 十六进制 WINUSER.H 中的标识符 鼠标左键
1 01 VK_LBUTTON 鼠标左键
2 02 VK_RBUTTON 鼠标右键
3 03 VK_CANCEL Ctrl-Break
4 04 VK_MBUTTON 鼠标中键
8 08 VK_BACK 退格键(Backspace)
9 09 VK_TAB Tab 键
13 0D VK_RETURN 回车键
16 10 VK_SHIFT Shift 键
17 11 VK_CONTROL Ctrl 键
18 12 VK_MENU Alt 键
19 13 VK_PAUSE Pause 键
20 14 VK_CAPITAL 大写锁定键
27 1B VK_ESCAPE Esc 键
32 20 VK_SPACE 空格键
33 21 VK_PRIOR Page Up 键
34 22 VK_NEXT Page Down 键
35 23 VK_END End 键
36 24 VK_HOME Home 键
37 25 VK_LEFT 左箭头
38 26 VK_UP 上箭头
39 27 VK_RIGHT 右箭头
40 28 VK_DOWN 下箭头
44 2C VK_SNAPSHOT Print Screen 键
45 2D VK_INSERT Insert 键
46 2E VK_DELETE Del 键
48~57 30~39 主键盘上的 0~9
65~90 41~5A A~Z
91 5B VK_LWIN 左 Windows 键
92 5C VK_RWIN 右 Windows 键
96~105 60~69 VK_NUMPAD0~VK_NUMPAD9 数字锁定键打开时数字小键盘的 0~9
106 6A VK_MULTIPLY 数字键区的 *
107 6B VK_ADD 数字键区的 +
109 6D VK_SUBTRACT 数字键区的 -
110 6E VK_DECIMAL 数字键区的 .

111

6F VK_DIVIDE 数字键区的 /

112~123

70~7B VK_F1~VK_F12 功能键 F1 ~ F24

144

90 VK_NUMLOCK 数字锁定键

145

91 VK_SCROLL Scroll Lock 键

(注意,数字键和字母键的虚拟键代码就是 ASCII 码)

 

lParam 信息:

 wParam 消息参数包含虚拟键代码,lParam 消息参数包含了帮助理解击键的其他有用信息。

32 位的 lParam 消息被分成了 6 个字段,如图:

重复计数:

重复计数是消息所表示的击键数目。大多数情况下,它被设置为 1。

但是,如果你按下一个键不放,且窗口过程不足够快,跟不上输入速率来处理击键消息,

Windows 就会把一些 WM_KEYDOWN 和 WM_SYSKEYDOWN 消息合并成一个单独的消息,并相应增加重复计数字段。

WM_KEYUP 和 WM_SYSKEYUP 消息的重复计数总是 1。

 

OEM 扫描码:

OEM 扫描码是键盘硬件产生的代码,由于严重依赖于键盘上键的分布,我们现在不再需要这种东西了。

扩展键标记:

Windows 程序通常忽略扩展键标记。

 

内容代码:

如果在击键的同时也按下了 Alt 键,则内容代码为 1。WM_SYSKEYUP 和 WM_SYSKEYDOWN 消息的此位始终为 1,

而 WM_KEYUP 和 WM_KEYDOWN 消息的此位始终为 0。有两种情况例外:

如果活动窗口最小化了,则它不具有输入焦点。所有的击键将产生 WM_SYSKEYUP 和 WM_SYSKEYDOWN 消息。

如果 Alt 键未被按下,内容代码字段将被设置为 0。

Windows 处理 WM_SYSKEYUP 和 WM_SYSKEYDOWN 消息,使最小化的活动窗口不处理这些击键。

在某些非英语键盘上,一些字符是通过 Shift 键,Ctrl 键 或 Alt 键同另一个键的组合产生的。

在这些情况下,内容代码被设置为 1,但消息并不是系统击键消息。

 

键的先前状态:

如果键以前是处于释放状态的,则键的先前状态为 0。而如果键以前是按下的,则键的先前状态为 1。

WM_KEYUP 和 WM_SYSKEYUP 消息的此字段总是为 1。

但 WM_KEYDOWN 和 WM_SYSKEYDOWN 消息的此字段可能为 0 或 1。

该位为 1 表明,消息为重复击键产生的第二个或后续发出的消息。

 

转换状态:

如果键正在被按下,转换状态为 0;如果键正在被释放,转换状态为 1。

WM_KEYDOWN 和 WM_SYSKEYDOWN 消息的此字段设置为 0,而 WM_KEYUP 和 WM_SYSKEYUP 消息的此字段设置为 1。

 

转义状态:

当处理击键消息时,你可能需要知道是否有转义键(Shift 键,Ctrl 键 和 Alt 键)

或切换键(Caps Lock 键,Num Lock 键 和 Scroll Lock 键) 被按下。

你能通过调用 GetKeyState() 获得此消息。

例如:iState = GetKeyState(VK_SHIFT) ;

如果 Shift 键被按下,则 iState 变量为负。如果 Caps Lockk 键打开,则从返回的值最低位置为 1。此位与键盘上的小灯保持一致。

 

GetMessageTime() 介绍:

           功能:该函数返回由GetMessage从当前线程队列里取得上一消息的消息时间。

                      时间是一个长整数,指定从系统开始到消息创建(即,放入线程消息队列)的占用时间(按毫秒计算)。

           函数原型:LONG GetMessageTime(VOID) ;

GetKeyState() 介绍:

          功能:该函数检取指定虚拟键的状态。

                     该状态指定此键是UP状态,DOWN状态,还是被触发的(开关每次按下此键时进行切换)。

          函数原型:SHORT GetKeyState(int nVirtKey) ;

          返回值:给出了给定虚拟键的状态,状态如下:
                         若高序位为1,则键处于DOWN状态,否则为UP状态。
                         若低序位为1,则键被触发。例如CAPS LOCK键,被找开时将被触发。
                         若低序位置为0,则键被关闭,且不被触发。触发键在键盘上的指示灯,当键被触发时即亮,键不被触发时即灭。

SendMessage() 介绍:

          功能:该函数将指定的消息发送到一个或多个窗口。

                    此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。

          函数原型:LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM IParam) ;

          参数:

                 hWnd:其窗口程序将接收消息的窗口的句柄。
                              如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,
                              包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
                 Msg:指定被发送的消息。
                 wParam:指定附加的消息特定信息。
                 IParam:指定附加的消息特定信息。
          返回值:返回值指定消息处理的结果,依赖于所发送的消息。

 

posted @ 2018-07-18 11:43  M-Anonymous  阅读(971)  评论(0)    收藏  举报