消息队列和GetMessage/PeekMessage、SendMessage/Postmesage的详解

一、消息队列

1.1 消息队列

消息队列是用来存放消息的一个队列,消息在队列中先入先出,所有的窗口程序都具有消息队列,程序可以从队列中获取消息。

1.2 消息队列的类型

系统消息队列:由操作系统维护的消息队列,存放系统产生的消息,如鼠标、键盘消息等等。

程序消息队列:属于每一个应用程序(线程)的消息队列,用应用程序维护。

当产生鼠标、键盘等消息时,消息先存放到系统消息队列,然后操作系统根据存放的消息找到对应的窗口的消息队列,将消息投递到窗口的消息队列中。

1.3 队列消息和非队列消息

队列消息:消息发出后,首先放入队列,然后通过消息循环获取。常见的队列消息:键盘、鼠标、定时器消息等等。

非队列消息:消息发出后,直接找到窗口的消息处理函数,调用消息处理函数进行处理,无需经过消息队列。常见的非队列消息:WM_PAINT、WM_SIZE等等。

二、消息循环和GetMessage/PeekMessage

2.1 消息循环

一般的消息循环如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

void Message(HWND hWnd) 

    MSG nMsg = { 0 };

    while (GetMessage(&nMsg, hWnd, 0, 0)) 

    

        TranslateMessage(&nMsg); 

        DispatchMessage(&nMsg); 

 

        if(nMsg.message == WM_PAINT)

        {

            char buff[30]={};

            sprintf(buff,"处理消息%d\n",nMsg.message);

            WriteConsole(hOutput,buff,sizeof(buff),NULL,NULL);

        }

    

}

GetMessage/PeekMessage:从程序的消息队列当中获取消息。

TranslateMessage:将键盘上的按键等消息翻译成字符消息。

DispatchMessage:将翻译后的消息再次放入到程序的消息队列中。

2.2 GetMessage和PeekMessage

1

2

3

4

5

6

GetMessage(

LPMSG lpMsg,

HWND hWnd,

UINT wMsgFilterMin,

UINT wMsgFilterMax

)

lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin:指定被检索的最小消息值的整数
wMsgFilterMax:指定被检索的最大消息值的整数。
返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多的错误信息,请调用GetLastError函数。

1

2

3

4

5

6

7

BOOL PeekMessage(

LPMSG IpMsg,

HWND hWnd,

UINT wMSGfilterMin,

UINT wMsgFilterMax,

UINT wRemoveMsg

);

lpMsg:接收消息信息的MSG结构指针。
hWnd:其消息被检查的窗口句柄。
wMsgFilterMin:指定被检查的消息范围里的第一个消息。
wMsgFilterMax:指定被检查的消息范围里的最后一个消息。
wRemoveMsg:确定消息如何被处理。此参数可取下列值之一:

意义

PM_NOREMOVE

PeekMessage处理后,消息不从队列里除掉。

PM_REMOVE

PeekMessage处理后,消息从队列里除掉。

PM_NOYIELD

此标志使系统不释放等待调用程序空闲的线程。可将PM_NOYIELD随意组合到PM_NOREMOVE或PM_REMOVE。


GetMessage和PeekMessage的主要区别在于:GetMessage是阻塞函数,它会在消息循环中会一直阻塞直到消息队列中出现了消息可以被获取,而PeekMessage是非阻塞函数,不管有没有获取到消息队列中的消息,它都会返回。PeekMessage更多用来检测消息队里中是否有消息,它的最后一个参数可以用来指定获取到消息后要不要把消息从消息队列中移除,通常情况下通过PeekMessage检测到消息队列有消息之后,再调用GetMessage区获取。

2.3 GetMessage/PeekMessage获取消息的过程

1、先在程序的消息队列中查找消息,如果有队列消息,就取出消息。

2、如果程序的消息队列中没有消息,向系统的消息队列获取属于本程序的消息。如果系统的消息队列中有属于本程序的消息,系统的消息队列会将消息分发到本程序的消息队列中。

3、如果系统的消息队列也没有消息,检查窗口需要绘制的区域是否需要重绘,如果发现有需要重绘的区域,产生WM_PAINT消息。

4、如果没有重新绘制区域,检查是否具有到时的定时器,如果有产生WM_TIMER定时器消息。

5、如果没有到时的定时器,整理程序的资源、内存等等。

三、SendMessage和PostMessage

1

2

3

4

5

6

LRESULT SendMessage(

HWND hWnd,

UINT Msg,

WPARAM wParam,

LPARAM IParam

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

1

2

3

4

5

6

BOOL WINAPI PostMessage(

HWND hWnd,

UINT Msg,

WPARAM wParam,

LPARAM lParam

);

hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:
HWND_BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、 被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口
NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样
Msg:指定被寄送的消息。
wParam:指定附加的消息特定的信息。
LParam:指定附加的消息特定的信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零

1、SendMessage

发送消息到指定的窗口,并等候对方将消息处理,为阻塞函数,获取消息的执行结果后返回。主要需要发送非队列消息,发送的消息不经过消息队列。

2、PostMessage

发送消息到程序的消息队列,不管消息有没有被处理都会立即返回,用于队列消息的发送

以上就是Win32 SDK基础(十一)之消息队列和GetMessage/PeekMessage、SendMessage/Postmesage的详解的详细内容,更多请关注php中文网其它相关文章!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GetMessagePeekMessage是Windows API中用于处理消息队列的函数。它们的主要区别如下: 1. GetMessage的主要功能是从消息队列中“取出”消息,消息被取出以后,就从消息队列中将其删除;而PeekMessage的主要功能是“窥视”消息,如果有消息,就返回true,否则返回false。PeekMessage也可以从消息队列中取出消息,这要用到它的一个参数(UINT wRemoveMsg),如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出。 2. 如果GetMessage消息队列中取不到消息,则线程就会被操作系统挂起,等到操作系统重新调度该线程时才会继续执行;而PeekMessage不会挂起线程,如果没有消息,它会立即返回,并且线程会继续执行。 3. GetMessage每次都会等待消息,直到取到消息才返回;而PeekMessage只是查询消息队列,没有消息就立即返回,从返回值判断是否取到了消息。 综上所述,GetMessagePeekMessage的区别在于GetMessage会阻塞线程并且从消息队列中删除消息,而PeekMessage不会阻塞线程并且可以选择是否删除消息。 #### 引用[.reference_title] - *1* *2* [GetMessagePeekmessage区别](https://blog.csdn.net/lala_achun/article/details/6201486)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [GetMessagePeekMessage 的区别](https://blog.csdn.net/hellokandy/article/details/52275366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值