前言
各位师傅大家好,我是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;
}
画图演示:
通过鼠标左键按住滑动 绘制图形
总结
学习了键盘消息和鼠标消息的原理和使用,下一章节我们学习控件的相关知识