Windows基础知识(2)
Windows基础知识(2)——鼠标键盘消息处理
前置芝士
焦点
一般来说,我们选中一个窗口就叫获取了一个焦点,键盘输入事件只会发送给具有焦点的窗口或者是控件。我们按下一个按键,会将我们的按键格式化成一个消息给内核,内核通过打包这个消息发送给具有焦点的窗体应用程序。
键盘事件
我们可以处理的键盘按键大致分为两类:
- 系统按键:WM_KEYDOWN,WM_KEYUP。
- 非系统按键:WM_SYSKEYDOWN,WM_SYSKEYUP。
WM_KEYDOWN 事件表示一个键按下,如果一直按住会持续地发送此类消息。
| 1 | case WM_KEYDOWN: { | 
WM_KEYUP 就是键盘弹起事件。
判断有没有按住某个按键使用 GetKeyBoardState(nVirtKey),参数是虚拟键码,如果按住这个键则返回 <0 的值。
下面是常见键盘键码的说明:
| 返回的常量 | Value | 说明 | 
|---|---|---|
| VK_LBUTTON | 0x01 | 鼠标左键 | 
| VK_RBUTTON | 0x02 | 鼠标右键 | 
| VK_CANCEL | 0x03 | 控制中断处理 | 
| VK_MBUTTON | 0x04 | 中间鼠标按钮 (三键鼠标) | 
| VK_XBUTTON1 | 0x05 | X1 鼠标按钮 | 
| VK_XBUTTON2 | 0x06 | X2 鼠标按钮 | 
| - | 0x07 | Undefined | 
| VK_BACK | 0x08 | BACKSPACE 密钥 | 
| VK_TAB | 0x09 | Tab 键 | 
| - | 0x0A-0B | 预留 | 
| VK_CLEAR | 0x0C | CLEAR 键 | 
| VK_RETURN | 0x0D | Enter 键 | 
| - | 0x0E-0F | Undefined | 
| VK_SHIFT | 0x10 | SHIFT 键 | 
| VK_CONTROL | 0x11 | Ctrl 键 | 
| VK_MENU | 0x12 | Alt 键 | 
| VK_PAUSE | 0x13 | PAUSE 键 | 
| VK_CAPITAL | 0x14 | CAPS LOCK 键 | 
| VK_KANA | 0x15 | IME Kana 模式 | 
| VK_HANGUEL | 0x15 | IME 朝鲜文库埃尔模式 (保持兼容性;使用 VK_HANGUL) | 
| VK_HANGUL | 0x15 | IME Hanguel 模式 | 
| VK_IME_ON | 0x16 | IME On | 
| VK_JUNJA | 0x17 | IME Junja 模式 | 
| VK_FINAL | 0x18 | IME 最终模式 | 
| VK_HANJA | 0x19 | IME Hanja 模式 | 
| VK_KANJI | 0x19 | IME Kanji 模式 | 
| VK_IME_OFF | 0x1A | IME 关闭 | 
| VK_ESCAPE | 0x1B | ESC 键 | 
| VK_CONVERT | 0x1C | IME 转换 | 
| VK_NONCONVERT | 0x1D | IME 不转换 | 
| VK_ACCEPT | 0x1E | IME 接受 | 
| VK_MODECHANGE | 0x1F | IME 模式更改请求 | 
| VK_SPACE | 0x20 | 空格键 | 
| VK_PRIOR | 0x21 | PAGE UP 键 | 
| VK_NEXT | 0x22 | PAGE DOWN 键 | 
| VK_END | 0x23 | END 键 | 
| VK_HOME | 0x24 | HOME 键 | 
| VK_LEFT | 0x25 | 向左键 | 
| VK_UP | 0x26 | 向上键 | 
| VK_RIGHT | 0x27 | 向右键 | 
| VK_DOWN | 0x28 | 向下键 | 
| VK_SELECT | 0x29 | SELECT 键 | 
| VK_PRINT | 0x2A | PRINT 键 | 
| VK_EXECUTE | 0x2B | EXECUTE 键 | 
| VK_SNAPSHOT | 0x2C | 打印屏幕键 | 
| VK_INSERT | 0x2D | INS 密钥 | 
| VK_DELETE | 0x2E | DEL 键 | 
| VK_HELP | 0x2F | 帮助密钥 | 
| - | 0x3A-40 | Undefined | 
| 0x41 | 密钥 | |
| VK_LWIN | 0x5B | 左Windows键 (自然键盘) | 
| VK_RWIN | 0x5C | 右Windows键 (自然键盘) | 
| VK_APPS | 0x5D | 应用程序键 (自然键盘) | 
| - | 0x5E | 保留 | 
| VK_SLEEP | 0x5F | 计算机休眠键 | 
| VK_NUMPAD0 | 0x60 | 数字键盘 0 键 | 
| VK_NUMPAD1 | 0x61 | 数字键盘 1 键 | 
| VK_NUMPAD2 | 0x62 | 数字键盘 2 键 | 
| VK_NUMPAD3 | 0x63 | 数字键盘 3 键 | 
| VK_NUMPAD4 | 0x64 | 数字键盘 4 键 | 
| VK_NUMPAD5 | 0x65 | 数字键盘 5 键 | 
| VK_NUMPAD6 | 0x66 | 数字键盘 6 键 | 
| VK_NUMPAD7 | 0x67 | 数字键盘 7 键 | 
| VK_NUMPAD8 | 0x68 | 数字键盘 8 键 | 
| VK_NUMPAD9 | 0x69 | 数字键盘 9 键 | 
| VK_MULTIPLY | 0x6A | 乘键 | 
| VK_ADD | 0x6B | 添加密钥 | 
| VK_SEPARATOR | 0x6C | 分隔符键 | 
| VK_SUBTRACT | 0x6D | 减去键 | 
| VK_DECIMAL | 0x6E | 十进制键 | 
| VK_DIVIDE | 0x6F | 除键 | 
| VK_F1 | 0x70 | F1 键 | 
| VK_F2 | 0x71 | F2 键 | 
| VK_F3 | 0x72 | F3 键 | 
| VK_F4 | 0x73 | F4 键 | 
| VK_F5 | 0x74 | F5 键 | 
| VK_F6 | 0x75 | F6 键 | 
| VK_F7 | 0x76 | F7 键 | 
| VK_F8 | 0x77 | F8 键 | 
| VK_F9 | 0x78 | F9 键 | 
| VK_F10 | 0x79 | F10 键 | 
| VK_F11 | 0x7A | F11 键 | 
| VK_F12 | 0x7B | F12 键 | 
| VK_F13 | 0x7C | F13 键 | 
| VK_F14 | 0x7D | F14 键 | 
| VK_F15 | 0x7E | F15 键 | 
| VK_F16 | 0x7F | F16 键 | 
| VK_F17 | 0x80 | F17 键 | 
| VK_F18 | 0x81 | F18 键 | 
| VK_F19 | 0x82 | F19 键 | 
| VK_F20 | 0x83 | F20 键 | 
| VK_F21 | 0x84 | F21 键 | 
| VK_F22 | 0x85 | F22 键 | 
| VK_F23 | 0x86 | F23 键 | 
| VK_F24 | 0x87 | F24 键 | 
| - | 0x88-8F | 未分配 | 
| VK_NUMLOCK | 0x90 | NUM LOCK 密钥 | 
| VK_SCROLL | 0x91 | SCROLL LOCK 键 | 
| 0x92-96 | OEM 特定 | |
| - | 0x97-9F | 未分配 | 
| VK_LSHIFT | 0xA0 | 左 SHIFT 键 | 
| VK_RSHIFT | 0xA1 | 右 SHIFT 键 | 
| VK_LCONTROL | 0xA2 | 左 Ctrl 键 | 
| VK_RCONTROL | 0xA3 | 右 Ctrl 键 | 
| VK_LMENU | 0xA4 | 左 Alt 键 | 
| VK_RMENU | 0xA5 | 右 ALT 键 | 
| VK_BROWSER_BACK | 0xA6 | 浏览器后退键 | 
| VK_BROWSER_FORWARD | 0xA7 | 浏览器前进键 | 
| VK_BROWSER_REFRESH | 0xA8 | 浏览器刷新键 | 
| VK_BROWSER_STOP | 0xA9 | 浏览器停止键 | 
| VK_BROWSER_SEARCH | 0xAA | 浏览器搜索键 | 
| VK_BROWSER_FAVORITES | 0xAB | 浏览器收藏键 | 
| VK_BROWSER_HOME | 0xAC | 浏览器“开始”和“主页”键 | 
| VK_VOLUME_MUTE | 0xAD | 静音键 | 
| VK_VOLUME_DOWN | 0xAE | 音量减小键 | 
| VK_VOLUME_UP | 0xAF | 音量增加键 | 
| VK_MEDIA_NEXT_TRACK | 0xB0 | 下一曲目键 | 
| VK_MEDIA_PREV_TRACK | 0xB1 | 上一曲目键 | 
| VK_MEDIA_STOP | 0xB2 | 停止媒体键 | 
| VK_MEDIA_PLAY_PAUSE | 0xB3 | 播放/暂停媒体键 | 
| VK_LAUNCH_MAIL | 0xB4 | 启动邮件键 | 
| VK_LAUNCH_MEDIA_SELECT | 0xB5 | 选择媒体键 | 
| VK_LAUNCH_APP1 | 0xB6 | 启动应用程序 1 键 | 
| VK_LAUNCH_APP2 | 0xB7 | 启动应用程序 2 键 | 
| - | 0xB8-B9 | 预留 | 
| VK_OEM_1 | 0xBA | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“;:”键 | 
| VK_OEM_PLUS | 0xBB | 对于任何国家/地区,“+”键 | 
| VK_OEM_COMMA | 0xBC | 对于任何国家/地区,“,键 | 
| VK_OEM_MINUS | 0xBD | 对于任何国家/地区,“-”键 | 
| VK_OEM_PERIOD | 0xBE | 对于任何国家/地区,“.”键 | 
| VK_OEM_2 | 0xBF | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“/?” key | 
| VK_OEM_3 | 0xC0 | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“~”键 | 
| - | 0xC1-D7 | 预留 | 
| - | 0xD8-DA | 未分配 | 
| VK_OEM_4 | 0xDB | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“[{”键 | 
| VK_OEM_5 | 0xDC | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“|”键 | 
| VK_OEM_6 | 0xDD | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“]}”键 | 
| VK_OEM_7 | 0xDE | 用于其他字符;它可能因键盘而异。 对于美国标准键盘,“单引号/双引号”键 | 
| VK_OEM_8 | 0xDF | 用于其他字符;它可能因键盘而异。 | 
| - | 0xE0 | 保留 | 
| 0xE1 | OEM 特定 | |
| VK_OEM_102 | 0xE2 | <>美国标准键盘上的键,或`\ | 
| 0xE3-E4 | OEM 特定 | |
| VK_PROCESSKEY | 0xE5 | IME PROCESS 密钥 | 
| 0xE6 | OEM 特定 | |
| VK_PACKET | 0xE7 | 用于将 Unicode 字符当作键击传递。 该 VK_PACKET键是用于非键盘输入方法的 32 位虚拟键值的低字。 有关详细信息,请参阅“备注”,以及KEYBDINPUTSendInputWM_KEYDOWNWM_KEYUP | 
| - | 0xE8 | 未分配 | 
| 0xE9-F5 | OEM 特定 | |
| VK_ATTN | 0xF6 | Attn 键 | 
| VK_CRSEL | 0xF7 | CrSel 键 | 
| VK_EXSEL | 0xF8 | ExSel 密钥 | 
| VK_EREOF | 0xF9 | 擦除 EOF 密钥 | 
| VK_PLAY | 0xFA | 播放键 | 
| VK_ZOOM | 0xFB | 缩放键 | 
| VK_NONAME | 0xFC | 预留 | 
| VK_PA1 | 0xFD | PA1 键 | 
| VK_OEM_CLEAR | 0xFE | 清除键 | 
在上面,大写字母和数字就是它对应的 ASCII 值。
这里再学习几个 API:
SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 用于向指定窗口发送一个消息,它的参数和主过程调用函数一致,通过这个我们可以自定义消息类型。
寻找窗口句柄,可以根据窗口类,也可以根据窗口标题,FindWindowA([in, optional] LPCSTR lpClassName,[in, optional] LPCSTR lpWindowName); 函数,当我们不需要使用窗口类寻找时,就把窗口类参数置为 NULL 即可。
鼠标事件
三种状态,三个按钮。
所谓三个按钮就是:
- 左键(LBUTTON)
- 中键(RBUTTON)
- 右键(MBUTTON)
所谓三个状态就是:
- 单击(DOWN,UP)
- 双击(DBLCLK)
- 拖动
一般来说,
WM_开头的宏都是顶层 Message 事件。
这三个按键,三个状态可以组成九种不同的消息,在这九个消息中,鼠标的位置被记录在了 lparam 参数中,低 16 位表示了 x 轴的坐标,高 16 位表示了 y 轴的坐标。
wParam 记录了同时间有没有其它按键,使用 MK_LBUTTON & wParam 可以判断是否按下了左键。
据此,我们可以写一个直线绘制的项目
| 1 | case WM_LBUTTONDOWN: { | 
主要原理就是在按下左键的时候记录坐标,弹起时创建画笔并绘制。
 
