窗口以击键消息和字符消息的形式接收键盘输入。附加到窗口的消息循环必须包含将击键消息转换为相应字符消息的代码。如果窗口在其客户区显示键盘输入,它应该创建并显示一个插入符号以指示将输入下一个字符的位置。
当用户在键盘上键入时,具有键盘焦点的窗口的窗口过程接收按键消息。击键消息是WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP。典型的窗口过程会忽略除WM_KEYDOWN之外的所有按键消息。当用户按下某个键时,系统会发布WM_KEYDOWN消息。
WM_KEYDOWN:当按下非系统键时,发布到具有键盘焦点的窗口。非系统键是在未按下 ALT 键时按下的键。"Alt”键又名交替换档键、更改键、替换键,因为它是英语单词“Alternate”(交换、替换)的缩写,大多数情况下与其它键组合使用。在没有鼠标的情况下,使用"Alt”键可以很容易地打开软件的菜单。
当窗口过程收到WM_KEYDOWN消息时,它应该检查伴随消息的虚拟键代码以确定如何处理击键。虚拟键代码在消息的wParam参数中。通常,应用程序仅处理由非字符键(包括功能键、光标移动键和专用键(如 INS、DEL、HOME 和 END))生成的击键。
以下示例显示了典型应用程序用于接收和处理按键消息的窗口过程框架。
case WM_KEYDOWN:
switch (wParam)
{
case VK_LEFT:
// Process the LEFT ARROW key.
break;
case VK_RIGHT:
// Process the RIGHT ARROW key.
break;
case VK_UP:
// Process the UP ARROW key.
break;
case VK_DOWN:
// Process the DOWN ARROW key.
break;
case VK_HOME:
// Process the HOME key.
break;
case VK_END:
// Process the END key.
break;
case VK_INSERT:
// Process the INS key.
break;
case VK_DELETE:
// Process the DEL key.
break;
case VK_F2:
// Process the F2 key.
break;
// Process other non-character keystrokes.
default:
break;
}
任何从用户接收字符输入的线程都必须在其消息循环中包含TranslateMessage函数。此函数检查击键消息的虚拟键代码,如果代码对应于字符,则将字符消息放入消息队列中。字符消息在消息循环的下一次迭代中被移除和调度;消息的wParam参数包含字符代码。
通常,线程的消息循环应该使用TranslateMessage函数来翻译每条消息,而不仅仅是虚拟键消息。虽然TranslateMessage对其他类型的消息没有影响,但它保证键盘输入被正确翻译。以下示例显示了如何在典型的线程消息循环中包含TranslateMessage函数。
MSG msg;
BOOL bRet;
while (( bRet = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0)
{
if (bRet == -1);
{
// handle the error and possibly exit
}
else
{
if (TranslateAccelerator(hwndMain, haccl, &msg) == 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
当TranslateMessage函数翻译与字符键对应的虚拟键代码时,窗口过程接收字符消息。字符消息是WM_CHAR、WM_DEADCHAR、WM_SYSCHAR和WM_SYSDEADCHAR。典型的窗口过程会忽略除WM_CHAR之外的所有字符消息。
所述的TranslateMessage函数生成一个WM_CHAR当用户按下任何下列键的消息:
任意字符键
BACKSPACE 退格
ENTER(回车)
ESC 退出
SHIFT+ENTER(换行)
TAB
当窗口过程接收到WM_CHAR消息时,它应该检查伴随消息的字符代码以确定如何处理该字符。字符代码在消息的wParam参数中。
以下示例显示了典型应用程序用于接收和处理字符消息的窗口过程框架。
case WM_CHAR:
switch (wParam)
{
case 0x08:
// Process a backspace.
break;
case 0x0A:
// Process a linefeed.
break;
case 0x1B:
// Process an escape.
break;
case 0x09:
// Process a tab.
break;
case 0x0D:
// Process a carriage return.
break;
default:
// Process displayable characters.
break;
}
WM_KEYDOWN和WM_CHAR都是键盘消息。TranslateMessage函数已经将按键消息转换成字符消息了,那么WndProc函数中需要对事件进行选择。如:键入“D”键,就应该选择WM_CHAR,因为WM_CHAR 只是字母,不包含特殊字符如Ctrl等。
如果键盘键入的是“Ctrl+D”,则应该选择WM_KEYDOWN,因为WM_KEYDOWN既包含字母也包含特殊字符。
WM_CHAR是由WM_KEYDOWN消息Translate()之后产生的,然后再发送给窗口过程。例如按下“D”键,产生WM_KEYDOWN消息,此消息经过Translate()处理后变成了WM_KEYDOWN、WM_CHAR两个消息传递给窗口过程。
而WM_SYSKEYDOWN是接受快捷键或系统命令按键的,像Alt键就是。所以捕获Alt键时,在WM_KEYDOWN下是无效的,要在WM_SYSKEYDOWN中。Ctrl和shift不属于WM_SYSKEYDOWN。

