2.5 消息循环的原理

消息循环的阻塞

GetMessage

  • 从系统获取消息,将消息从系统中移除,阻塞函数。当系统无消息时,会等候下一条消息。

在这里插入图片描述
在我们看来,系统中无时无刻不存在消息,但是因为CPU的处理速度非常快,当遇到没有消息时,我们的程序就会经常阻塞。就像上面一样,我们这样写消息循环,效率极低,为了提高效率就有了PeekMessage。

PeekMessage

以查看的方式从系统获取消息,可以不将消息从系统移除,非阻塞函数。当系统无消息时,返回FALSE,继续执行后续代码。

BOOL PeekMessage(
  LPMSG lpMsg,	//指向MSG结构的指针,用于存储检索到的消息
  HWND hWnd,	//要检索其消息的窗口句柄。如果为0,则检索当前线程所有窗口的消息
  UINT wMsgFilterMin,
  UINT wMsgFilterMax,
  UINT wRemoveMsg
);

参数说明:

  • lpMsg: 指向MSG结构的指针,用于存储检索到的消息.
  • hWnd: 要检索其消息的窗口句柄。如果为0,则检索当前线程所有窗口的消息.
  • wMsgFilterMin 和 wMsgFilterMax: 指定要检索的消息范围。如果都为0,则检索所有消息.
  • wRemoveMsg: 指定消息处理选项,如PM_REMOVE(检索并移除消息,即获取这条消息)或PM_NOREMOVE(只检索不移除消息).

返回值:

  • 如果有消息,返回非零值(TRUE)
  • 如果没有消息,返回零(FALSE)
  • 如果出现错误(如参数无效),可能返回-1

可以把它理解为侦察兵,它去系统判断有没有消息,但有消息时返回TRUE,我们再使用GetMessage去获取消息进行处理,没有消息时也不影响,会继续执行后续代码。

在这里插入图片描述
如果是以前的消息循环,相当于没有消息时程序休眠了,但是此时程序依旧在工作

发送消息

SendMessage

  • 向指定的窗口发送一条消息,并等待窗口处理完该消息后才返回
LRESULT SendMessage(
  HWND hWnd,
  UINT Msg,
  WPARAM wParam,
  LPARAM lParam
);

参数说明:

  • hWnd: 接收消息的窗口句柄。如果设为HWND_BROADCAST,消息将被发送到所有顶级窗口.
  • Msg: 要发送的消息。可以是系统定义的消息或自定义消息.
  • wParam和lParam: 附加的消息特定信息.

从参数看可以发现和消息的组成一样,但是这里只有前四个,缺少的两部分由函数内部自己补充

typedef struct tagMSG {
    HWND   hwnd;    // 消息所属的窗口句柄
    UINT   message; // 消息标识符
    WPARAM wParam;  // 消息的附加参数1
    LPARAM lParam;  // 消息的附加参数2
    DWORD  time;    // 消息产生的时间戳
    POINT  pt;      // 消息产生时鼠标指针的屏幕坐标
} MSG, *PMSG;

返回值:

  • 返回值取决于发送的消息,通常是消息处理的结果.

我们尝试使用一下,之前退出都是使用PostQuitMessage(0),我们现在自己发送WM_QUIT看看,由于不知道PostQuitMessage(0)内部使用的是SendMessage还是PostMessage,这里我们都试一下,如果点击关闭直接退出,说明调用的就是SendMessage
在这里插入图片描述
换成PostMessage后程序成功退出了,说明PostQuitMessage(0)内部调用的是PostMessage。

这里分析一下,PostMessage将WM_QUIT发送到某个地方,GetMessage抓到了这个消息,所以程序退出了,而SendMessage却没有,说明GetMessage没有抓到SendMessage发送的这条WM_QUIT消息,说明PostMessage和SendMessage将消息发送到了不同的地方,这里后续再解答

PostMessage

  • 将一条消息放入与指定窗口关联的线程消息队列中,然后立即返回,不等待消息被处理.
BOOL PostMessageA(
  HWND hWnd,
  UINT Msg,
  WPARAM wParam,
  LPARAM lParam
);

);

参数说明:

  • hWnd: 接收消息的窗口句柄。如果为HWND_BROADCAST,消息将被发送到所有顶级窗口.
  • Msg: 要发送的消息。可以是系统定义的消息或自定义消息.
  • wParam和lParam: 附加的消息特定信息.

返回值:

  • 如果函数成功,返回非零值.
  • 如果函数失败,返回零. 可以通过GetLastError获取更多错误信息.

PostMessage与SendMessage的区别

  • PostMessage是异步的,将消息放入队列后立即返回;而SendMessage是同步的,会等待消息处理完成.
  • PostMessage适用于非紧急的消息传递,SendMessage适用于需要立即响应的情况.

消息分类

  • 系统消息
    ID范围: 0 - 0x03FF
    由系统定义好的消息,可以在程序中直接使用。

  • 用户自定义的消息
    ID范围:0X0400 - 0X7FFF(31743)
    由用户自己定义,满足用户自己的需求。由用户自己发出消息,并响应处理。

自定义消息宏:WM_USER

我们自己定义一个看看

首先定义一个宏,消息常量
在这里插入图片描述

发送消息
在这里插入图片描述
处理消息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 30
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦里捡到一只猫丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值