1. 谁获得了焦点(光标)
有时输入焦点不在任何视窗中。这种情况发生在所有程式都是最小化的时候。这时,Windows 将继续向活动视窗发送键盘讯息,但是这些讯息与发送给非
最小化的活动视窗的键盘讯息有不同的形式。
视窗讯息处理程式通过拦截WM_SETFOCUS和WM_KILLFOCUS讯息来判定它的
视窗何时拥有输入焦点。WM_SETFOCUS 指示视窗正在得到输入焦点,
WM_KILLFOCUS 表示视窗正在失去输入焦点。我将在本章的後面详细说明这些讯
息。
2. 伫列和同步
当使用者按下并释放键盘上的键时,Windows 和键盘驱动程式将硬体扫描码
转换为格式讯息。然而,这些讯息并不保存在讯息伫列中。实际上,Windows 在
所谓的「系统讯息伫列」中保存这些讯息。系统讯息伫列是独立的讯息伫列,
它由Windows 维护,用於初步保存使用者从键盘和滑鼠输入的资讯。只有当
Windows应用程式处理完前一个使用者输入讯息时,Windows 才会从系统讯息伫
列中取出下一个讯息,并将其放入应用程式的讯息伫列中。
此过程分为两步:首先在系统讯息伫列中保存讯息,然後将它们放入应用
程式的讯息伫列,其原因是需要同步。就像我们刚才所学的,假定接收键盘输
入的视窗就是有输入焦点的视窗。使用者的输入速度可能比应用程式处理按键
的速度快,并且特定的按键可能会使焦点从一个视窗切换到另一个视窗,後来
的按键就输入到了另一个视窗。但如果後来的按键已经记下了目标视窗的位址,
并放入了应用程式讯息伫列,那么後来的按键就不能输入到另一个视窗。
3. 按键信息
键按下 键释放非系统键 WM_KEYDOWN WM_KEYUP
系统键 WM_SYSKEYDOWN WM_SYSKEYUP
4. 虚拟键码
按下键盘时,WndProc 参数message为 M_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP在IBM 相容机种上,扫描码
16 是Q 键,17 是W 键,18 是E、19 是R,20 是T,21 是Y 等等。这时您会发现,
扫描码是依据键盘的实际布局的。Windows 开发者认为这些代码过於与设备相关
了,於是他们试图通过定义所谓的虚拟键码,以便经由与装置无关的方式处理
键盘。其中一些虚拟键码不能在IBM 相容机种上产生,但可能会在其他制造商
生产的键盘中找到,或者在未来的键盘上找到。
在wndProc中Wparam中包含以下虚拟按键的号码,更具体含义在lparam
虚拟键码
十进位 十六进位 WINUSER.H 识别字 必需? IBM 相容键盘
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
12 0C VK_CLEAR Num Lock 关闭时的数字键盘5
13 0D VK_RETURN √ Enter (或者另一个)
16 10 VK_SHIFT √ Shift (或者另一个)
17 11 VK_CONTROL √ Ctrl (或者另一个)
18 12 VK_MENU √ Alt (或者另一个)
19 13 VK_PAUSE Pause
20 14 VK_CAPITAL √ Caps Lock
27 1B VK_ESCAPE √ Esc
32 20 VK_SPACE √ Spacebar
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 √ 下箭头
41 29 VK_SELECT
42 2A VK_PRINT
43 2B VK_EXECUTE
44 2C VK_SNAPSHOT Print Screen
45 2D VK_INSERT √ Insert
46 2E VK_DELETE √ Delete
47 2F VK_HELP
等等
lparam资讯(wparam讯息参数含有上面所讨论的虚拟键码)
在四个按键讯息(WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP)
中,wParam 讯息参数含有上面所讨论的虚拟键码,而lParam 讯息参数则含有对
了解按键非常有用的其他资讯。lParam 的32 位分为6 个栏位
重复计数repeat count 重复计数是该讯息所表示的按键次数
OEM扫描码OEM Scan Code OEM 扫描码是由硬体(键盘)产生的代码
扩充键旗标(Extend key flag)
如果按键结果来自IBM 增强键盘的附加键之一,那么扩充键旗标为1(IBM
增强型键盘有101 或102 个键。功能键在键盘顶端,游标移动键从数字键盘中
分离出来,但在数字键盘上还保留有游标移动键的功能)。对键盘右端的Alt
和Ctrl键,以及不是数字键盘那部分的游标移动键(包括Insert和Delete键)、
数字键盘上的斜线(/)和Enter 键以及Num Lock 键等,此旗标均被设定为1。
Windows 程式通常忽略扩充键旗标。
内容代码(Context code)
右按键时,假如同时压下ALT 键,那么内容代码为1。对WM_SYSKEYUP 与
WM_SYSKEYDOWN 而言,此位元总视为1;而对WM_ KEYUP 与WM_KEYDOW 讯息而言,
此位元为0。除了两个之外:
如果活动视窗最小化了,则它没有输入焦点。这时候所有的按键都会产生
WM_SYSKEYUP 和WM_SYSKEYDOWN 讯息。如果Alt键未被按下,则内容代码栏位被
设定为0。Windows 使用WM_SYSKEYUP 和WM_SYSKEYDOWN 讯息,从而使最小化了
的活动视窗不处理这些按键。
对於一些外国语文(非英文)键盘,有些字元是通过Shift、Ctrl 或者Alt
键与其他键相组合而产生的。这时内容代码为1,但是此讯息并非系统按键讯息。
键的先前状态(Previous key state)
如果在此之前键是释放的,则键的先前状态为0,否则为1
转换状态(Transition state)
如果键正被按下,则转换状态为0;如果键正被释放,则转换状态为1
位移状态
在处理按键讯息时,您可能需要知道是否按下了位移键(Shift、Ctrl 和
Alt)或开关键(Caps Lock、Num Lock和Scroll Lock)。通过呼叫GetKeyState
(Extended Key Flag)
(Context Code)
(Previous Key State)
(Transition State)
bbs.theithome.com
Programming Windows 程式开发设计指南(Windows95 程序设计 第五版)
第 199 页
函式,您就能获得此资讯。例如:
iState = GetKeyState (VK_SHIFT) ;
如果按下了Shift,则iState 值为负(即设定了最高位置位元)。如果Caps
Lock 键打开,则从
iState = GetKeyState (VK_CAPITAL) ;
传回的值低位元被设为1。此位元与键盘上的小灯保持一致。
5. SendMessage发送程式讯息
在Windows 中,这种方法是可行的。发送讯息的函式叫做SendMessage,它所用的参数与传递到视窗讯息处理程式的参数是相同的:
SendMessage (hwnd, message, wParam, lParam) ;
在呼叫SendMessage 时,Windows 呼叫视窗代号为hwnd 的视窗讯息处理程
式,并把这四个参数传给它.当视窗讯息处理程式完成讯息处理之後,Windows
把控制传回到SendMessage 呼叫之後的下一道叙述。您发送讯息过去的视窗讯
息处理程式,可以是同一个视窗讯息处理程式、同一程式中的其他视窗讯息处
理程式或者其他应用程式,中的视窗讯息处理程式。
6. TranslateMessage
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
TranslateMessage 函式,它将按键讯息转换为字元讯
息。如果讯息为WM_KEYDOWN 或者WM_SYSKEYDOWN,并且按键与位移状态相组合
产生一个字元,则TranslateMessage把字元讯息放入讯息伫列中。此字元讯息
将是GetMessage 从讯息伫列中得到的按键讯息之後的下一个讯息。