09 Windows编程——键盘消息

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

活动窗口:活动窗口通常是很好鉴别的。它总是最上层的窗口——也就是说,它的父窗口句柄是NULL。

系统消息队列 & 应用程序消息队列

当用户按下和释放键盘上的一个键时,Windows和键盘设备驱动程序将硬件扫描码转换为格式化后的消息。但是,这些消息并不立即被放入应用程序消息队列,而是由Wimdows把这些消息存储在系统消息队列中。系统消息队列是一个单独的消息队列,它被 Windows用来初步存储用户从键盘和鼠标输入的消息。仅当Windows应用程序完成了对前一个用户输入消息的处理后,Windows才从系统消息队列中取出下一条消息,并把它放入应用程序消息队列。

应用程序从Windows接收的关于键盘事件的消息可分为击键消息和字符消息两种。对产生可显示字符的击键组合,Windows在发送击键消息的同时还发送字符消息。有些键不产生字符,如Shift键、功能键、光标移动键和特殊字符键(如Insert键和Delete键)。对于这些键,Windows只产生击键消息。

字符消息

WM_CHAR,WM_SYSCHAR,WM_DEADCHAR,WM_SYSDEADCHAR

wParam就是按键字符,TCHAR(wParam)就可以获得这个字符,不要去区分这个字符是ASCII字符或者UNICODE字符,因为TCHAR数据类型已经帮你区分好了!

一个按键会产生以下4个消息:WM_KEYDOWN,WM_CHAR,WM_KEYUP,WM_DEADCHAR 4个消息。

击键消息

09 Windows编程——键盘消息

通常键按下消息和键释放消息是成对出现的。但是如果你按下一个键不放时,则被认为发生了一次连续按键(自动重复)行为,Windows将发送给窗口过程一连串的WM KEYDOWN(或WMSYSKEYDOWN)消息。当此键最终被释放时,Windows发送给窗口过程一个WMKEYUP(或WMSYSKEYUP)消息。像所有的队列消息一样,击键消息是可被实时追踪的。你能通过调用GetMessageTime函数,得到键被按下或释放的相对时间。

系统击键

表明该击键对Windows比对Windows应用程序更加重要。当输入键和Alt键组合时通常产生的是WM SYSKEYDOWN和WMSYSKEYUP消息。应用程序通常忽略WMSYSKEYUP和WMSYSKEYDOWN消息,将它们交付给DefWindowProc函数完成默认处理。因为Windows关注所有的Alt键功能逻辑,应用程序就不必处理这些消息。如果你非要处理这些消息,则在处理完毕后,仍然需要发送这些消息给DefWindowProc函数,以便不影响Windows对它的处理。

对所有四类击键消息,wParam是虚拟键代码,用于标识哪个键被按下或被释放,而IParam包含属于本次击键的一些其他数据。大多数虚拟键代码命名是以VK_开头的,它定义在WINUSER日头文件中。lParam消息参数包含了帮助理解击键的其他有用信息。32位的lParam消息被分成了6个字段,如图所示。

09 Windows编程——键盘消息

 #include<Windows.h>
#include<WinUser.h>
#include<tchar.h>
#include<stdio.h> LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
{
WNDCLASS WndClass;
TCHAR* ClassName = TEXT("MyClass");
HWND hwnd;
MSG msg; WndClass.cbClsExtra = ;
WndClass.cbWndExtra = ;
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + );
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInst;
WndClass.lpfnWndProc = WindProc;
WndClass.lpszClassName = ClassName;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_VREDRAW | CS_HREDRAW; RegisterClass(&WndClass);
hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, , , NULL, NULL, hInst, NULL);
ShowWindow(hwnd, nShow);
UpdateWindow(hwnd); while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return ;
} LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT pt;
static int cx, cy;
static int cyChar;
static int iLine;
static int iMaxLine;
static TCHAR cBuf[] = { "Please Press Key:" };
TEXTMETRIC tm;
RECT rect;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
cyChar = tm.tmHeight;
ReleaseDC(hwnd, hdc);
iLine = ;
iMaxLine = ;
return ;
case WM_SIZE:
cx = LOWORD(lParam);
cy = HIWORD(lParam);
iMaxLine = cy / cyChar-;
iLine = iLine > iMaxLine ? iMaxLine : iLine;
return ;
case WM_PAINT:
hdc = BeginPaint(hwnd, &pt);
TextOut(hdc, pt.rcPaint.left, pt.rcPaint.top, cBuf, _tcslen(cBuf));
EndPaint(hwnd, &pt);
iLine++;
return ;
case WM_CHAR:
iLine = iLine > iMaxLine ? iMaxLine : iLine;
_stprintf(cBuf, TEXT("lParam=0x%X wParam=0x%X : %c"), lParam, wParam,wParam);
rect.left = ;
rect.top = iLine * cyChar;
rect.right = cx;
rect.bottom = (iLine + )*cyChar;
InvalidateRect(hwnd, &rect, TRUE);
return ;
case WM_DESTROY:
PostQuitMessage();
return ;
default:
break;
} return DefWindowProc(hwnd, message, wParam, lParam);
}
上一篇:Windows程序设计2(消息机制、菜单)


下一篇:rabbitmq之消息重入队列