第六章 键盘消息

来源:互联网 发布:小学英语课文朗读软件 编辑:程序博客网 时间:2024/06/02 09:23

 

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

 WM_SETFOCUS 表明窗口正在接受输入焦点。

WM_KILLFOCUS 表明窗口正在失去输入焦点。

应用程序从Windows接收的关于键盘事件的消息可分为击键和字符两种。

击键:如键盘上的仅有一个键标“A”。按下此键是一次击键,释放此键也认为是一次击键。

字符:键盘也是能产生可显示字符或者控制字符的输入设备。“A”键能产生一些不同的字符,这取决于同Ctrl、Shift、Caps Lock键的组合。

通常地,此字符为小写字母“a”。如果Shift键被按下或者Caps Lock被锁定,此字符就为大写字母“A”。如果Ctrl键被按下,此字符就是Ctrl + A

 

对产生可显示字符的击键组合,Windows在发送击键消息的同时还发送字符消息。

有些键不产生字符,如Shift键、功能键、光标移动键和特殊字符键。对于这些键,Windows只产生击键消息。

击键消息

 键按下键释放

非系统键击

WM_KEYDOWNWM_KEYUP系统键击WM_SYSKEYDOWNWM_SYSYKEYUP

通常键按下消息和键释放消息是成对出现的。像所有的队列消息一样,击键消息可被实时追踪的。通过调用GetMessageTime函数,得到键被按下释放的相对时间。

系统键击 和 非系统键击

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

当输入键和Alt 键组合时通常产生的是WM_SYSYKEYDOWN 和 WM_SYSYKEYUP 消息。这些按键调用程序菜单或系统菜单选项,被用来实现系统功能如转换活动窗口,

或作为系统快捷键。应用程序通常忽略WM_SYSYKEYDOWN 和 WM_SYSYKEYUP消息,将它们交给DefWindowProc函数完成默认处理。

因为Windows关注所有的Alt键功能逻辑,应用程序就不必处理这些消息。

不与Alt组合时按下和释放键会产生WM_KEYDOWN 和 WM_KEYUP消息。应用程序可以使用或者丢弃这些击键消息。Windows也不处理它们。

虚拟键代码

对于所有四类击键消息,wParam是虚拟键代码,用于标识哪个键被按下或被释放,而lParam包含属于本次击键的一些其他数据。

虚拟键代码存储在 WM_KEYDOWN 、WM_KEYUP 、 WM_SYSYKEYDOWN、 WM_SYSYKEYUP消息的wParam参数中。此代码确定哪个键被按下或被释放。

经常使用的大多数键代码命名是以 VK_ 开头的,它定义在WINUSER.H头文件中。

lparam消息

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

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

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

OEM扫描码:是键盘硬件产生的代码。Windows通常几乎忽略OEM扫描码,除非是它要依赖于键盘上键的分布。

扩展键标记:Windows通常忽略扩展键标记。

内容代码:如果击键的同时也按下了Alt键,则内容代码为 1 。 ~~

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

WM_KEYUP 和 WM_SYSYKEYUP消息的此字段总是 1.

但WM_SYSKEYDOWN 、WM_KEYDOWN消息的此字段可能为0或1.该位为1表明,消息为重复击键产生的第二个或后续发出的消息。

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

WM_SYSKEYDOWN 、WM_KEYDOWN消息的此字段设置为0,WM_KEYUP 和 WM_SYSYKEYUP消息的此字段设置为1

程序实例:

如果单独的处理WM_KEYDOWN逻辑,这样不管任何时候想修改滚动条逻辑,就不得不在WM_KEYDOWN消息上做同样的改变。

我们可以通过给窗口过程发送假冒的消息欺骗WndProc函数,使它认为收到了滚动条消息。Windows允许你这样做。

SendMessage函数携带了传给窗口过程的参数:

SendMessage(hwnd, message, wParam, lParam);

下面是用光标移动键实现滚动条逻辑代码:

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){static int cxChar,cyChar,cxCaps,cyClient;int i, y, iVertPos, iPaintBeg, iPaintEnd;char szBuffer[10];HDChdc;TEXTMETRICtm;PAINTSTRUCT ps;SCROLLINFOsi;switch (message){case WM_CREATE:hdc = GetDC(hwnd);GetTextMetrics(hdc,&tm);cxChar = tm.tmAveCharWidth;cyChar = tm.tmHeight + tm.tmExternalLeading;cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;ReleaseDC(hwnd,hdc);return 0;case WM_SIZE:cyClient= HIWORD(lParam);si.cbSize= sizeof(si);si.fMask= SIF_PAGE|SIF_RANGE;si.nMin= 0;si.nMax= NUMLINES - 1;si.nPage= cyClient / cyChar;SetScrollInfo(hwnd,SB_VERT,&si,TRUE);return 0;case WM_VSCROLL:si.cbSize= sizeof(si);si.fMask= SIF_ALL;GetScrollInfo(hwnd,SB_VERT,&si);iVertPos = si.nPos;switch (LOWORD(wParam)){case SB_TOP:si.nPos = si.nMin;break;case SB_BOTTOM:si.nPos = si.nMax;break;case SB_LINEUP:si.nPos -= 1;break;case SB_LINEDOWN:si.nPos += 1;break;case SB_PAGEUP:si.nPos -= si.nPage;break;case SB_PAGEDOWN:si.nPos+= si.nPage;break;case SB_THUMBPOSITION:si.nPos = si.nTrackPos;break;default:break;}si.fMask= SIF_POS;SetScrollInfo(hwnd,SB_VERT,&si,TRUE);GetScrollInfo(hwnd,SB_VERT,&si);if(si.nPos != iVertPos){ScrollWindow(hwnd, 0, cyChar*(iVertPos - si.nPos),NULL,NULL);UpdateWindow(hwnd);}return 0;case WM_KEYDOWN:switch (wParam){case VK_HOME:SendMessage(hwnd,WM_VSCROLL,SB_TOP,0);break;case VK_END:SendMessage(hwnd,WM_VSCROLL,SB_BOTTOM,0);break;case VK_PRIOR:SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,0);break;case VK_NEXT:SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,0);break;case VK_UP:SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,0);break;case VK_DOWN:SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,0);break;case VK_LEFT:SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,0);break;case VK_RIGHT:SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,0);break;}return 0;case WM_PAINT:hdc= BeginPaint(hwnd,&ps);si.cbSize= sizeof(si);si.fMask= SIF_POS;GetScrollInfo(hwnd,SB_VERT,&si);iVertPos= si.nPos;iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar);iPaintEnd = min(NUMLINES - 1, iVertPos + ps.rcPaint.bottom / cyChar);for (i = iPaintBeg; i <= iPaintEnd; i++){y = cyChar* (i - iVertPos);TextOut(hdc,0,y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel));TextOut(hdc,22*cxCaps,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc));SetTextAlign(hdc,TA_TOP|TA_RIGHT);TextOut(hdc,22*cxCaps + 40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics(sysmetrics[i].iIndex)));SetTextAlign(hdc,TA_TOP|TA_LEFT);}EndPaint(hwnd,&ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd,message,wParam,lParam);}

字符消息:

四类字符消息

 字符死字符非系统字符WM_CHARWM_DEADCHAR系统字符WM_SYSCHARWM_SYSDEADCHAR
WM_CHAR 、 WM_DEADCHAR 来自于 WM_KEYDOWN消息
WM_SYSCHAR、WM_SYSDEADCHAR来自于 WM_SYSKEYDOWN消息

Windows通常只处理 WM_CHAR消息,而忽略其它三个。

typedef struct tagMSG {  HWND   hwnd;   UINT   message;   WPARAM wParam;   LPARAM lParam;   DWORD  time;   POINT  pt; } MSG, *PMSG; 


 

 

 

0 0
原创粉丝点击