前面讨论了利用位移状态信息把按键消息翻译为字符消息的方法,并且提到,仅利用转换状态信息还不够,因为还需要知道与国家/地区有关的键盘配置。由于这个原因,您不应该试图把按键消息翻译为字符代码。Windows会为您完成这一工作,在前面我们曾看到过以下的程序代码:
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
这是WinMain中典型的消息循环。GetMessage函数用队列中的下一个消息填入msg结构的字段。DispatchMessage以此消息为参数呼叫适当的窗口消息处理程序。
在这两个函数之间是TranslateMessage函数,它将按键消息转换为字符消息。如果消息为WM_KEYDOWN或者WM_SYSKEYDOWN,并且按键与位移状态相组合产生一个字符,则TranslateMessage把字符消息放入消息队列中。此字符消息将是GetMessage从消息队列中得到的按键消息之后的下一个消息。
消息顺序
因为TranslateMessage函数从WM_KEYDOWN和WM_SYSKEYDOWN消息产生了字符消息,所以字符消息是夹在按键消息之间传递给窗口消息处理程序的。例如,如果Caps Lock未打开,而使用者按下再释放A键,则窗口消息处理程序将接收到如表6-10所示的三个消息:
| 表6-10 |
| 消息 | 按键或者代码 |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「a」的字符代码(0x61) |
| WM_KEYUP | 「A」的虚拟键码(0x41) |
如果您按下Shift键,再按下A键,然后释放A键,再释放Shift键,就会输入大写的A,而窗口消息处理程序会接收到五个消息,如表6-11所示:
| 表6-11 |
| 消息 | 按键或者代码 |
| WM_KEYDOWN | 虚拟键码VK_SHIFT (0x10) |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「A」的字符代码(0x41) |
| WM_KEYUP | 「A」的虚拟键码(0x41) |
| WM_KEYUP | 虚拟键码VK_SHIFT(0x10) |
Shift键本身不产生字符消息。
如果使用者按住A键,以使自动重复产生一系列的按键,那么对每条WM_KEYDOWN消息,都会得到一条字符消息,如表6-12所示:
| 表6-12 |
| 消息 | 按键或者代码 |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「a」的字符代码(0x61) |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「a」的字符代码(0x61) |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「a」的字符代码(0x61) |
| WM_KEYDOWN | 「A」的虚拟键码(0x41) |
| WM_CHAR | 「a」的字符代码(0x61) |
| WM_KEYUP | 「A」的虚拟键码(0x41) |
如果某些WM_KEYDOWN消息的重复计数大于1,那么相应的WM_CHAR消息将具有同样的重复计数。
组合使用Ctrl键与字母键会产生从0x01(Ctrl-A)到0x1A(Ctrl-Z)的ASCII控制代码,其中的某些控制代码也可以由表6-13列出的键产生:
| 表6-13 |
| 按键 | 字符代码 | 产生方法 | ANSI C控制字符 |
| Backspace | 0x08 | Ctrl-H | /b |
| Tab | 0x09 | Ctrl-I | /t |
| Ctrl-Enter | 0x0A | Ctrl-J | /n |
| Enter | 0x0D | Ctrl-M | /r |
| Esc | 0x1B | Ctrl-[ |
|
最右列给出了在ANSI C中定义的控制字符,它们用于描述这些键的字符代码。
有时Windows程序将Ctrl与字母键的组合用作菜单快捷键此时,不会将字母键转换成字符消息。
经过10年的考虑(回顾这些年来我写过的Windows程序代码),我更喜欢将Tab、Enter、Backspace和Escape键处理成控制字符,而不是虚拟键。我通常这样处理WM_CHAR:
case WM_CHAR:
//其它行程序
switch (wParam)
{
case '/b': // backspace
//其它行程序
break ;
case '/t': // tab
//其它行程序
break ;
case '/n': // linefeed
//其它行程序
break ;
case '/r': // carriage return
//其它行程序
break ;
default: // character codes
//其它行程序
break ;
}
return 0 ;

852

被折叠的 条评论
为什么被折叠?



