Windows --- 自定义消息以及Windows对话框原理

接: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);
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuqiuyaq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值