SendMessage、PostMessage、PostThreadMessage

本文详细介绍了Windows编程中SendMessage和PostMessage函数的区别与用法。解释了如何使用这些函数向窗口发送消息,以及如何处理自定义消息。此外还讨论了PreTranslateMessage的作用及局限性,并对比了两种消息发送方式的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  SendMessage函数将指定的消息发送到一个或多个窗口,消息会直接发送到窗口过程而不经过消息队列,且直到消息处理完成后,SendMessage才返回。函数返回值指定消息处理的结果,依赖于所发送的消息。函数原型:

 

LRESULT WINAPI SendMessage(
        HWND hWnd,
        UINT Msg,
        WPARAM wParam,
        LPARAM lParam
); <span style="font-size:14px;"> 
</span>

 

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

  Msg:要发送的消息。

  wParam:消息的附加信息。

  IParam:消息的附加信息

有穿过消息队列的消息才能被虚函数PreTranslateMessage()截获,故采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息不会被PreTranslateMessage()截获。

  PostMessage函数将一个消息放入(寄送)到与指定窗口创建的线程相关联的消息队列里,不等待线程处理消息就立刻返回。消息队列里的消息通过调用GetMessage或PeekMessage取得。函数执行成功返回非0,否则返回0。函数参数意义与SendMessage相同。

系统只对系统级的消息(0 ~ WM_USER-1)进行封送处理。发送自定义消息(>= WM_USER)到另一个进程,你需要自己对消息进行封送处理。
如果发送一个范围低于 WM_USER 的消息给异步消息函数(PostMessage、  SendNotifyMessageSendMessageCallback),它的消息参数不能包含指针。否则,操作将失败。函数将在接收线程处理消息之前返回,发送者将在内存被使用之前释放。
请不要使用 PostMessage 函数投递 WM_QUIT 消息;应该使用 PostQuitMessage 函数代替。

  对于接收消息的窗口,有两种处理消息的方法:

1、重写PreTranslateMessage来截获消息,只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。

2、添加以下代码来处理自定义消息:

①、自定义消息ID:
#define WM_MY_MESSAGE(WM_USER + 100)
②、添加消息处理函数:
protected:
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam)
    {
        ......
    }
③、映射消息ID和消息处理函数:
BEGIN_MESSAGE_MAP(CMFCApplication17Dlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDOK, &CMFCApplication17Dlg::OnBnClickedOk)
    ON_WM_TIMER()
    ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage) //映射消息ID和消息处理函数
END_MESSAGE_MAP()

BOOL WINAPI PostMessage(
            HWND hWnd,
            UINT Msg,
            WPARAM wParam,
            LPARAM lParam
);
  

 

  从以上两个函数的功能可以看出SendMessage与PostMessage最大的区别有两点:1、SendMessage发送的消息不会进队而PostMessage发送的消息会进队。2、SendMessage属于阻塞函数,PostMessage属于非阻塞函数。3、如果需要等消息处理完后才进入下一流程则使用SendMessage(),如果想要发送消息后程序继续执行下一条语句则使用PostMessage()。

  PostThreadMessage函数用来向线程发送消息,对于线程消息,MSG结构体中hwnd成员应为NULL。收消息的线程也必须有message queue(消息队列)。

参考:http://baike.baidu.com/link?url=BDv2_a-uBVOVe1jzJ1kZ7Q4SYoI5qP1Eq4JBqA60luNQT5a1urd1H2GihkvMU2PWLLzZ8UnRub3XsCriNaWuEq

            http://baike.baidu.com/link?url=COaT6VDTfb0OmuACYswtZtYL8UoAa1z55fS4WZIfRBq9c4Enn3BeXv2IS9zoQEvLqD_fQMeT8_Sxxqyj6WGW0a

在异步线程中使用PostMessagePostThreadMessage发送消息,可以向指定的窗口或线程发送消息,让其在消息循环中处理。一般情况下,我们可以自定义特定的消息类型来传递数据或通知事件。 具体实现可以参考以下步骤: 1. 定义消息类型,可以使用WM_APP+数字来定义自定义消息类型,例如#define WM_MY_MESSAGE (WM_APP + 1)。 2. 使用PostMessagePostThreadMessage发送消息,其中PostMessage用于向指定的窗口发送消息,PostThreadMessage用于向指定的线程发送消息。例如,可以使用以下代码向指定窗口发送消息: ``` HWND hWnd = ::FindWindow(NULL, _T("Window Title")); if (hWnd != NULL) { ::PostMessage(hWnd, WM_MY_MESSAGE, WPARAM wParam, LPARAM lParam); } ``` 3. 在窗口或线程的消息循环中处理自定义消息。 对于窗口,可以在WndProc函数中添加对自定义消息的处理,例如: ``` LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_MY_MESSAGE: // 处理自定义消息 break; // 其他消息处理 } return DefWindowProc(hWnd, message, wParam, lParam); } ``` 对于线程,可以在线程函数中使用GetMessage或PeekMessage函数获取消息并处理,例如: ``` DWORD WINAPI ThreadFunc(LPVOID lpParam) { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_MY_MESSAGE) { // 处理自定义消息 } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return 0; } ``` 需要注意的是,PostMessagePostThreadMessage是异步发送消息,即发送后不会等待消息处理完毕再返回。如果需要同步发送消息并等待处理完毕再返回,可以使用SendMessageSendMessageTimeout函数。同时,由于异步发送消息可能会导致消息被快速发送过多,因此在发送消息前应该加入消息队列,保证消息的顺序和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值