消息循环的阻塞
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
我们自己定义一个看看
首先定义一个宏,消息常量
发送消息
处理消息