接:Windows --- 常用消息以及消息附加参数_小雪菜本菜的博客-CSDN博客
按键的时候,如何捕获到按下的是组合键呢?
组合键一般捕获的是系统按键,想要知道它按的是哪个键,想要知道哪个键按没按下它的状态
GetKeyState function (winuser.h) - Win32 apps | Microsoft Docs
返回一个状态值,如果最高位是 1,表示已经按下;否则就是抬起
一个 short 两个字节,如果是 1 表示键已经按下,如果是 0 就是抬起
最高位是 1 就是负数(符号位),负数小于 0,就可以判断当前键是按下还是抬起
由于 A 是一瞬间的,需要先按 shift 键
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//键盘按下
case WM_KEYDOWN:
{
switch(wParam)
{
//按下字母'A'
case 0x41:
{
//判断按下字母'A'的同时有没有按系统键 GetKeyState可以获取系统键的状态
//可以判断某个键在某一个时刻是按下还是抬起
if (GetKeyState(VK_SHIFT) < 0)
{
MessageBox(hWnd, L"SHIFT + A",L"提示",MB_OK);
break;
}
}
}
//调用操作系统默认窗口处理函数
//如果不想自己处理、处理不了...调用这个函数就交给操作系统处理
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
}
保存返回值
- 128 是一个负数,负数最高位为 1
只要调用 ShowWindow(hWnd,SW_SHOW),窗口大小就会改变
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//窗口大小发生变化就会产生这个消息
case WM_SIZE:
//窗口一出来窗口大小就改变了 最大化最小化同样如此
SetWindowText(hWnd, L"窗口大小改变");
break;
}
//调用操作系统默认窗口处理函数
//如果不想自己处理、处理不了...调用这个函数就交给操作系统处理
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
以现在这种方式不能判断连续按两个键,现在的消息机制只能帮你捕获第一个,只能通过一个去判断另一个,不能直接判断两个,只能先判断当前按了哪一个,再去看另一个的状态
Windows --- 常用消息以及消息附加参数_小雪菜本菜的博客-CSDN博客_windows 常用消息
只要调用 UpdateWindow(hWnd);就会产生 WM_PAINT 绘图消息,所以这个消息也是没有进队列的
发送消息
上面的消息都是由于窗口大小改变,或者点击按钮的时候发出来的,那么我们能不能自己发出一些消息出来呢?
鼠标点击一下就发送一个消息,有两种方式,PostMessage 和 SendMessage
发出 WM_CLOSE 消息
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//窗口大小发生变化的消息
case WM_LBUTTONDOWN:
//发出消息
//发出 WM_CLOSE 消息 窗口句柄:要往哪个窗口发送的消息 要发送的消息:关闭消息
//关闭消息的 wParam 和 lParam 没有使用 都为 0
SendMessage(hWnd,WM_CLOSE,0,0);
//发出 WM_CLOSE 消息
PostMessage(hWnd,WM_CLOSE,0,0);
//发出键盘按键消息
//'A'键存储在 wParam
SendMessage(hWnd,WM_KEYDOWN,0x41,0);
PostMessage(hWnd,WM_KEYDOWN,0x41,0);
break;
//窗口关闭消息
case WM_CLOSE:
if(IDYES == MessageBox(NULL,L"您确定要退出吗?",L"提示",MB_YESNO))
{
//销毁当前处理的窗口句柄-> 发出 WM_DESTROY 信息
//DestroyWindow(hWnd);
//最终系统都会给你处理一遍
return 0;
}
else
{ //如果不执行break
break;
}
break;
//键盘按下
case WM_KEYDOWN:
{
switch(wParam)
{
//回车
case VK_RETURN:
MessageBox(hWnd,"按下了回车符",L"提示",MB_OK);
break;
//空格
case VK_SPACE:
SetWindowText(hWnd,L"按下了空格键");
break;
//按下ESC键
case VK_ESCAPE:
SetWindowText(hWnd,L"按下了ESC键");
break;
//按下SHIFT键
case VK_SHIFT:
SetWindowText(hWnd,L"按下了Shift键");
break;
//按下F1键
case VK_F1:
SetWindowText(hWnd,L"按下了F1键");
break;
//注意按下字母键的区别
//按下A键
case 0x41:
SetWindowText(hWnd,L"按下了A键");
break;
//数字分为字母上边的数字和小键盘的数字
//按下数字0 字母上边的数字
case 0x30:
SetWindowText(hWnd,L"按下了字母上边数字0键");
break;
//按下数字0 小键盘的数字
case VK_NUMPAD0:
SetWindowText(hWnd,L"按下了小键盘数字0键");
break;
}
break;
}
}
//调用操作系统默认窗口处理函数
//如果不想自己处理、处理不了...调用这个函数就交给操作系统处理
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
PostMessage 和 SendMessage 的区别
一、SendMessage 是阻塞的,PostMessage 是非阻塞的
需要等弹框结束后( 需要等 WM_KEYDOWN 消息处理完之后 )才会执行下一条语句
SendMessage 是阻塞消息:等待返回指定消息处理的结果:结果就是 WM_KEYDOWN 给它返回的结果,需要等 WM_KEYDOWN 处理完之后它才会返回
SendMessage function (winuser.h) - Win32 apps | Microsoft Docs
PostMessage 直接就下来了,没有等待 WM_KEYDOWN 消息的执行,只是做一个通知
SendMessage 返回 666,这个结果就会传递到 n
按下 A 键后
SendMessage 的返回值就是 WM_KEYDOWN 这个消息处理完之后的返回值
PostMessageA function (winuser.h) - Win32 apps | Microsoft Docs
二、如果 SendMessage 一直不返回,就一直阻塞
三、一般 SendMessage 用于进程内,PostMessage 用于进程外
能不能给另一个程序,例如记事本发一个 WM_CLOSE 消息?
首先需要查找到这个窗口
检查窗口类型名:Windows --- 常用消息以及消息附加参数_小雪菜本菜的博客-CSDN博客_windows 常用消息
FindWindow 每次只能找一个,如果有多个记事本会从第一个打开的一个个关闭
如果不知道窗口标题(写NULL),只知道窗口类型名,会找所有这种类型的窗口,如果只知道窗口的标题也是可以的
//设计窗口类里面的窗口类型名 窗口标题
HWND hNotepad = FindWindow(L"Notepad",L"无标题 - 记事本");
//等于NULL 说明没找到
//不为NULL 就发送消息
if (hNotepad != NULL)
{
//发送关闭消息:会关掉记事本
PostMessage(hNotepad,WM_CLOSE,0,0);
}
//设计窗口类里面的窗口类型名
HWND hNotepad = FindWindow(NULL,NULL);
//不为NULL 就发送消息
if (hNotepad != NULL)
{
PostMessage(hNotepad,WM_CLOSE,0,0);
}
自定义消息
系统消息(系统帮我们定义好的消息):WM_CLOSE、WM_SIZE. . .
用宏定义(消息不够用,想定义自己的消息):用户自定义消息,一定是在 1024 以上,1024 以下的消息都被系统定义了,避免与系统的消息冲突
//User Message
//自定义测试消息
#define UM_TEST WM_USER + 1
//用户自定义消息的分界线 十进制的 1024
#define WM_USER 0x0400
发送一个自定义消息并接收
系统消息 WM_CLOSE、WM_SIZE,每一个消息规定了参数 wParam,lParam 有什么含义
自定义消息的 wParam,lParam 需要自己定义(4 个字节的指针)
//发送一个自定义消息 wParam,lParam 自己需要定义
SendMessage(hWnd,UM_TEST,10,20);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//接收消息
//用户自定义消息 测试消息
case UM_TEST:
{
MessageBox(hWnd,L"这是测试消息",L"提示",MB_OK);
}
}
//调用操作系统默认窗口处理函数
//如果不想自己处理、处理不了...调用这个函数就交给操作系统处理
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}