[SDK]-键盘消息和鼠标消息
前言
各位师傅大家好,我是qmx_07,今天给大家讲解键盘消息和鼠标消息,下一节讲解控件的相关知识点
键盘消息
- 应用程序从windows接收的关于键盘事件的消息分为击键和字符两种
- windows再发送击键消息的同时 还会发送字符消息
- Shift、ctrl、alt、光标移动键盘,这些键值只会产生击键消息
系统按键与非系统按键
当键盘按下时,windows会将消息送到消息队列

- SYS代表系统,表示这个按键 对于应用程序来讲,更加重要
- 比如说 ALT+F4 关闭应用程序,ALT+TAB 换页,程序通常忽略WM_SYSKEYUP和WM_SYSKEYDOWN消息,并将它们传送到DefWindowProc。
- 由于Windows要处理所有Alt键的功能,所以不需要进行拦截消息
- WM_KEYDOWN和WM_KEYUP消息通常是在按下或者释放不带Alt键的键时产生的
虚拟键码
- 虚拟键码保存在WM_KEYDOWN,WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP消息的wParam参数中,该参数标识了按下或释放的键
获取键盘消息
LRESULT CALLBACK WndProc(
HWND hWnd,//窗口句柄
UINT message,//消息ID
WPARAM wParam, //虚拟码
LPARAM lParam)//键盘发过来的原始数据,转换为虚拟码
位移状态
- SHORT FLAG = GetKeyState (VK_SHIFT) & 0x8000; 如果按下了键盘按钮,则这个值为负,& 0x8000 会让系统更加稳定,减少出错
获取键盘消息
case WM_KEYDOWN:{switch (wParam){case VK_F1:{SHORT Flag = (GetKeyState(VK_SHIFT) & 0x8000);//判断SHIFT是否按下if (Flag < 0){MessageBox(NULL, L"SHIFT + F1", L"Msg", MB_OK);//SHIFT + F1同时按下}else{MessageBox(NULL, L"F1", L"Msg", MB_OK);//F1按下}break;}default:break;}break;}

- 通过GetKeyState()函数的方式,捕获多个按键消息
通过SendMessage()获取键盘消息
SendMessage(_In_ HWND hWnd,//窗口句柄_In_ UINT Msg,//消息 也就是到那个地方去处理_Pre_maybenull_ _Post_valid_ WPARAM wParam,//按下的按钮_Pre_maybenull_ _Post_valid_ LPARAM lParam);
我们也可以通过按下其他按键来向窗口模拟对应内容,比如说 我们想要通过按下F2,对应F1的按键内容

case WM_KEYDOWN:{switch (wParam){case VK_F1:{SHORT Flag = (GetKeyState(VK_SHIFT) & 0x8000);if (Flag < 0){MessageBox(NULL, L"SHIFT + F1", L"Msg", MB_OK);}else{MessageBox(NULL, L"F1", L"Msg", MB_OK);}break;}case VK_F2:{SendMessage(hWnd,WM_KEYDOWN, VK_F1, NULL);break;}default:break;}break;}
通过SendMessage()获取其他ID消息
case WM_KEYDOWN:{switch (wParam){case VK_F1:{SHORT Flag = (GetKeyState(VK_SHIFT) & 0x8000);if (Flag < 0){MessageBox(NULL, L"SHIFT + F1", L"Msg", MB_OK);}else{MessageBox(NULL, L"F1", L"Msg", MB_OK);}break;}case VK_F2:{SendMessage(hWnd,0x12138, 9999, NULL);break;}default:break;}break;}case 0x12138:{switch (wParam){case 9999:{MessageBox(NULL, L"MyMsg", L"Msg", MB_OK);break;}default:break;}}

- SendMessage函数,也可以向其他消息ID发送消息请求,来触发处理程序
FindWindow()函数 讲解
FindWindowW(_In_opt_ LPCWSTR lpClassName,//窗口类名_In_opt_ LPCWSTR lpWindowName);//窗口标题
- 用于在系统中查找具有指定类名和窗口名的顶级窗口


通过 FindWindow()函数来获取句柄,触发消息
case VK_F2:{HWND class_hwnd = FindWindow(L"qmx_07", NULL);HWND title_hwnd = FindWindow(NULL,L"demo");SendMessage(class_hwnd, WM_KEYDOWN, VK_F1, NULL);SendMessage(title_hwnd, 0x12138, 9999, NULL);break;}
鼠标消息
概念
- 三种状态:单击、双击、拖动
- 三个按钮:左键(LBUTTON)、右键(RBUTTON)、中键(MBUTTON)

1Param的结构解析
- 低16位存储X坐标:这部分数据表示鼠标光标的X轴位置。
- 高16位存储Y坐标:这部分数据表示鼠标光标的Y轴位置
宏的使用
- LOWORD宏提取X坐标
- HIWORD宏提取Y坐标
通过1Param参数,可以实时获取鼠标位置
wParam的含义
- 鼠标键状态标识:wParam用来标识鼠标键的状态,例如MK_LBUTTON代表鼠标左键
代码案例
通过鼠标 画线段
POINT Pos[2] = { 0 };
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_COMMAND:{int wmId = LOWORD(wParam);// 分析菜单选择:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}}break;case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps);// TODO: 在此处添加使用 hdc 的任何绘图代码...EndPaint(hWnd, &ps);}break;case WM_LBUTTONDOWN://获取起点的坐标位置{Pos[0].x = LOWORD(lParam);Pos[0].y = HIWORD(lParam);break;}case WM_LBUTTONUP://获取终点的坐标位置画图{Pos[1].x = LOWORD(lParam);Pos[1].y = HIWORD(lParam);HDC hDC = GetDC(hWnd);HPEN hpen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));SelectObject(hDC, hpen);POINT pi = { 0 };MoveToEx(hDC, Pos[0].x, Pos[0].y, &pi);LineTo(hDC, Pos[1].x, Pos[1].y);ReleaseDC(hWnd, hDC);break;}case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}
画面演示:

- 通过WM_LBUTTONDOWN 获取鼠标按下的位置,再通过WM_LBUTTONUP获取鼠标抬起的位置,就可以画出线段
通过 WM_MOUSEMOVE 按住鼠标左键 自由绘制图形
case WM_LBUTTONDOWN:{break;}case WM_LBUTTONUP:{break;}case WM_MOUSEMOVE:{if (wParam & WM_LBUTTONDOWN){int nPosX = LOWORD(lParam);int nPosY = HIWORD(lParam);HDC hDC = GetDC(hWnd);HPEN hpen = CreatePen(PS_SOLID, 8, RGB(255, 0, 0));SelectObject(hDC, hpen);POINT pi = { 0 };MoveToEx(hDC, nPosX, nPosY, &pi);LineTo(hDC, nPosX, nPosY);ReleaseDC(hWnd, hDC);}break;}
画图演示:

通过鼠标左键按住滑动 绘制图形
总结
学习了键盘消息和鼠标消息的原理和使用,下一章节我们学习控件的相关知识
