吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2716|回复: 16
收起左侧

[系统底层] win32笔记十三 消息类型

[复制链接]
huchen 发表于 2024-5-7 00:21
之前的笔记索引

消息类型

image-20240426152549256.png

当我们点击某个窗口,就会产生一个消息,操作系统就会得到这个消息,然后判断点在那个窗口上,找到后,会根据窗口的一个成员来找到是属于那个线程的,找到后,就会把封装好后的消息放在结构体里,存储到消息队列里来,应用层的GetMessage就会不停的从消息队列里取消息

MSG

看下代码中的MSG结构体的成员

/*
 * Message structure
 */
typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

消息由谁产生的呢?

  • 可能是鼠标
  • 可能是键盘
  • 可能是其他应用程序
  • 可能是内核程序

那这么多的消息,操作系统会把所有消息给他们分成不同的类别,每一种类型的消息起一个独一无二的编号,即message成员

hwnd

句柄,消息针对窗口

wParam,lParam

详细描述这个消息是什么样的,比如说,我按下键盘,message就会给我一个编号,至于我按的什么键等信息就会封装到wParam,lParam这两个成员

time

消息什么时候产生的

pt

这个消息在什么位置产生的,记录产生时的坐标

看着这些成员,就会明白为什么不直接处理消息,要分发了,因为这些成员只知道索引,不知道窗口函数在哪,所以没有办法,只能在传给分发函数,分发函数根据窗口句柄找到对应的窗口,然后从内核发起的调用

看这些成员可能你会觉得眼熟,发现不就是WindowProc里的函数吗,所以这些参数就是通过GetMessage来获得的

输出消息类型

LRESULT CALLBACK WindowProc(
                    HWND hwnd,      // handle to window
                    UINT uMsg,      // message identifier
                    WPARAM wParam,  // first message parameter
                    LPARAM lParam   // second message parameter
)
{
    char OutBuff[0x80];
    sprintf(OutBuff,"消息类型:%x\n",uMsg);
    OutputDebugString(OutBuff);

    return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

在原来的代码上加上这些

image-20240426160724109.png

得到这些类型,以1举例说明,在WinUser.h文件中可找到

#define WM_NULL                         0x0000
#define WM_CREATE                       0x0001
#define WM_DESTROY                      0x0002
#define WM_MOVE                         0x0003
#define WM_SIZE                         0x0005

知道当窗口创建的时候,内核就会创建1这样的消息,有些消息可以忽略的,只用找感兴趣的消息来做文章

这些消息是一直存在的,只要对应的线程不死,就会一直产生消息

所以当我把窗口关闭了,但在管理里还是能看到

image-20240426162256252.png

所以就要写一个代码来让程序真正的退出

通过上面的宏定义的名字,就能猜个大概了

关闭代码

LRESULT CALLBACK WindowProc(
                    HWND hwnd,      // handle to window
                    UINT uMsg,      // message identifier
                    WPARAM wParam,  // first message parameter
                    LPARAM lParam   // second message parameter
)
{
    switch(uMsg)
    {
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

PostQuitMessage

向系统指示线程已发出终止请求, (退出) 。 它通常用于响应 WM_DESTROY 消息。

这样点叉,去看管理器就没了

输出键盘消息

如果我想获取键盘消息的话,那么就要先知道是什么类型

类型是WM_KEYDOWN

image-20240426165436563.png

switch(uMsg)
    {
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    case WM_KEYDOWN:
        {
            MessageBox(0,0,0,0);
            return 0;
        }
    }

这样按下键盘就会弹出一个窗口,这样代表着能够捕捉到键盘消息

接下来就要显示了

去文档查具体的解释

WM_KEYDOWN

LRESULT CALLBACK WindowProc(
  HWND hwnd,       // handle to window
  UINT uMsg,       // WM_KEYDOWN
  WPARAM wParam,   // virtual-key code
  LPARAM lParam    // key data
);

wParam,   lParam这里的这两个参数就是详细信息的

wParam

虚拟码

lParam

其他辅助信息

image-20240426175122059.png

0~15:当前按键被按了几次

30:标明之前key的状态,值为1 ,则被按下过,为0则没有

switch(uMsg)
    {
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    case WM_KEYDOWN:
        {
            char OutBuff[0x80];
            sprintf(OutBuff,"消息:%x - %x - %x\n",uMsg,wParam,lParam);
            OutputDebugString(OutBuff);
            return 0;
        }
    }

image-20240426175749184.png

当我短按的时候就是1E0001,长按的时候就是401E0001

前面的0x41就是A的ASCII码

1E0001

000 0000    0   0001 1110   0000 0000 0000 0001

(31 30 29 …… 0)被按了一次,以前没有被按

401E0001

010 0000    0   0001 1110   0000 0000 0000 0001

一次,以前被按过

每个消息都会有这两个参数,而这个参数是根据消息类型来决定的,不同的消息类型对应的含义不同,比如

WM_DESTROY

LRESULT CALLBACK WindowProc(
  HWND hwnd,       // handle to window
  UINT uMsg,       // WM_DESTROY
  WPARAM wParam,   // not used
  LPARAM lParam    // not used
);

这两个参数就是无意义的

按什么键显示什么键

WM_CHAR

LRESULT CALLBACK WindowProc(
  HWND hwnd,       // handle to window
  UINT uMsg,       // WM_CHAR
  WPARAM wParam,   // character code (TCHAR)
  LPARAM lParam    // key data
);
wParam

具体的按键

TranslateMessage

将虚拟密钥消息转换为字符消息。 字符消息将发布到调用线程的消息队列,以便下次线程调用 GetMessagePeekMessage 函数时读取。

switch(uMsg)
    {
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    case WM_CHAR:
        {
            char OutBuff[0x80];
            sprintf(OutBuff,"消息:%c \n",wParam);
            OutputDebugString(OutBuff);
            return 0;
        }
    }

运行结果,别忘了把转换消息给去掉注释

image-20240426181927976.png

免费评分

参与人数 8吾爱币 +12 热心值 +8 收起 理由
asciibase64 + 1 谢谢@Thanks!
稻海香 + 2 + 1 我很赞同!可以分享下滴水的教程不
willJ + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
唐小样儿 + 1 + 1 我很赞同!
安道尔的鱼 + 1 + 1 我很赞同!
lgc81034 + 1 谢谢@Thanks!
hopecolor514 + 1 热心回复!
为之奈何? + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

GMCN 发表于 2024-5-7 02:59
在哪儿学习的
hopecolor514 发表于 2024-5-7 05:30
KellyCurtis168 发表于 2024-5-7 06:37
jituidadada 发表于 2024-5-7 08:03
学习点很nice,如果可以持续更新的话就更美了
bester 发表于 2024-5-7 08:51
似乎不能发送组合键呐 比如ctrl+alt+A
不变的信仰 发表于 2024-5-7 09:12
谢谢分享
nitian0963 发表于 2024-5-7 09:13

谢谢大佬,我要看完这个系列
yjs302 发表于 2024-5-7 09:52
感谢分享
 楼主| huchen 发表于 2024-5-7 09:53

滴水的视频
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-15 09:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表