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 位虚拟键值的低字。 有关详细信息,请参阅“备注”,以及KEYBDINPUT SendInput WM_KEYDOWN WM_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: { |
主要原理就是在按下左键的时候记录坐标,弹起时创建画笔并绘制。