1       故障现象

故障现象1:能够收到SendMessage()发出的消息,但收不到PostMessage()发出的消息。

故障现象2:能够收到PostMessage()发出的消息,但收不到SendMessage()发出的消息。

2       两个比喻

从发送端来说:

SendMessage()好比电信系统提供通话服务。

如果对方占线,立即返回。

如果对方不占线,就保持呼叫→接收端接听→通话→挂断。在挂断之前,发送端处于阻塞状态,不可以干别的事。

PostMessage()好比电子邮件系统提供电子邮件服务。

发送端把邮件交给电子邮件系统,然后立即返回,就可以干别的事了。

电子邮件系统将邮件放在队列缓存区中,缓慢地将邮件发送到接收端的邮箱里。

从接收端来说(!!! 关键 关键 关键 !!!)

要接收SendMessage()的消息,必须用手机接听,到邮箱里无法接收此类消息。

要接收PostMessage()的消息,必须到邮箱里接收,用手机无法接听此类消息。

1       技术原理

在本文中:

把SendMessage()发送的消息成为立即消息。

把PostMessage()发送的消息成为延迟消息。

 

在计算机系统里,立即消息和延迟消息分别使用完全不同的途径发送消息,必须采用相匹配的、完全不同的接收方法才能收到消息。

1.1      立即消息的收发

为了接收并处理立即消息,接收端应用程序必须准备一张(消息,处理函数)映射表,如下表所示:

消息

处理函数

WM_USER + 1

OnWmUser_1

WM_USER + 2

OnWmUser_2

WM_USER + n

OnWmUser_n

立即消息的发送与接收的协作流程如下表:

发送端应用程序

操作系统

接收端应用程序

(消息处理总入口函数)

发送消息

阻塞发送端应用程序

调用接收端应用程序的消息处理总入口函数

在(消息,处理函数)映射表中搜索与消息相匹配的处理函数,立即调用处理函数。

向操作系统返回处理结果

向发送端应用程序返回处理结果

解除阻塞发送端应用程序

接收消息处理结果

继续其它事务

1.2      延迟消息的收发

延迟消息的发送与接收的协作流程如下表:

发送端应用程序

操作系统

接收端应用程序

发送消息

将消息放入接收端应用程序的消息队列中

继续其它事务

从消息队列中取出消息慢慢处理。

2       具体实现

以C++ Builder为例。

2.1      接收立即消息

要接收立即消息,也就是由SendMessage()发送的消息。

步骤1:声明并定义消息处理函数

步骤2:声明和定义(消息,处理函数)映射表

class TForm2 :   public TForm

{

// 声明WM_COPYDATA 消息的处理函数

void __fastcall OnCopyData(const   TMessage &msg);

// 受理立即消息 --- 由 SendMessage() 发送的消息

// 声明和定义(消息,处理函数)映射表

BEGIN_MESSAGE_MAP

VCL_MESSAGE_HANDLER(WM_COPYDATA, TMessage, OnCopyData);

END_MESSAGE_MAP(TForm)

};

2.2      接收延迟消息

要接收延迟消息,也就是由PostMessage()发送的消息。

放置一个TApplicationEvents控件,该控件只能接收延迟消息,无法接收立即消息。

编写TApplicationEvents.OnMessage事件处理函数。如下表:

void __fastcall   TForm2::AppEventsMessage(tagMSG &Msg, bool &Handled)

{

// 若收到延迟消息WM_USER_1

if (Msg.message == WM_USER_1)

{

// 此处编写消息处理代码

// 设立标志,消息已被处理

Handled   = true;

}

else {

// 设立标志,消息未被处理

Handled = false;

}

}

3       结论

SendMessage()和PostMessage()的共性:

都能发送消息。

SendMessage和PostMessage的差异:

采用完全不同的途径发送消息,也要采用完全不同的方法和途径接收消息。

若接收途径与发送途径不匹配,就无法接收消息。

通过SendMessage()发送的消息,发送端发送并必须等待接收端处理,接收端立即处理并向发送端反馈处理结果,无延迟。

通过PostMessage()发送的消息,发送端发送后立即返回,不等待接收端不处理,接收端缓慢地延迟处理。

 

SendMessage

PostMessage()

发送端

直接发给接收端

要求接收端立即处理

在接收端处理完毕之前处于阻塞状态,不可以干别的事

可以立即获悉接收端的处理结果

消息经由OS缓存到接收端的消息队列里

发送完毕立即返回,可以干别的事

接收端

立即处理收到的消息

缓慢地从队列里取出消息并处理。

4       其它

SendMessage和PostMessage的其它特性,网上都有,本文不再重复与累述。

迥异和诡异的SendMessage和PostMessage的更多相关文章

  1. [转] - SendMessage、PostMessage原理

    SendMessage.PostMessage原理 本文讲解SendMessage.PostMessage两个函数的实现原理,分为三个步骤进行讲解,分别适合初级.中级.高级程序员进行理解,三个步骤分别 ...

  2. SendMessage、PostMessage原理

    SendMessage.PostMessage原理 本文讲解SendMessage.PostMessage两个函数的实现原理,分为三个步骤进行讲解,分别适合初级.中级.高级程序员进行理解,三个步骤分别 ...

  3. SendMessage和PostMessage区别以及WPARAM 和 LPARAM区别

    WPARAM 和 LPARAM wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:一个是WORD类型的16位整型变量:另一个是LONG类型 ...

  4. SENDMESSAGE和POSTMESSAGE

    原文:http://www.cnblogs.com/wind-net/archive/2012/11/01/2750123.html SendMessage 和 PostMessage 的区别 1.首 ...

  5. 关于SendMessage和PostMessage的理解的例子

    对于SendMessage 和 PostMessage 平时口头的解释是 SendMessage 发送消息后等待返回, PostMessage 发送消息后立即返回 . 但是这样解释还是不具体,什么叫等 ...

  6. sendmessage和postmessage的区别

    BOOL   PostMessage(          HWND   hWnd,             //   handle   of   destination   window        ...

  7. (转)深入解析SendMessage、PostMessage

        转自:http://blog.csdn.net/xt_xiaotian/article/details/2778689 本文将使用C++语言,在MFC框架的配合下给出PostMessage.S ...

  8. SendMessage 和 PostMessage

    1.首先是返回值意义的区别,我们先看一下 MSDN 里的声明: LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar ...

  9. MFC的sendmessage和postmessage 以及sendmessagetimeout

    PostMessage只负责将消息放到消息队列中,不确定何时及是否处理,相当于异步操作,执行后马上返回SendMessage要等到受到消息处理的返回码(DWord类型)后才继续,相当于同步操作,一直在 ...

随机推荐

  1. (springboot)自定义Starter

    要引入的jar项目,即自定义的Starter项目: pom:(这里不能引入springboot整合否则测试项目注入失败) <?xml version="1.0" encodi ...

  2. 轻松pick移动开发第一篇,flex布局

    一.什么是flex布局 首先提问一个问题,一般童鞋都会让子元素水平居中,那么怎么让子元素垂直居中呢?这里就要用到我们的flex布局了. 1.flex 是 flexible Box 的缩写,意为&quo ...

  3. Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)

    Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...

  4. .net core 微服务项目-介绍篇

    项目介绍 1.各种方式连接API都会连接到 APIGateway 来进行统一的分发 Ocelot 2.当api需要授权时 需要请求授权服务 IdentityServer4 3.授权服务对请求进行调用u ...

  5. egret之移除带参数的监听事件

    this.selectBtn.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onClickNewIndo.bind(this,this.data) ...

  6. ES5新增数组的一些方法

    1.Array.indexof(value1,value2) Tip:用于返回某个数组或字符串中规定字符或者字符串的位置. (1)当Array.indexof(value1);里面只有一个值的时候,表 ...

  7. mybatis 源码分析(七)KeyGenerator 详解

    一.KeyGenerator 概述 在平时开发的时候经常会有这样的需求,插入数据返回主键,或者插入数据之前需要获取主键,这样的需求在 mybatis 中也是支持的,其中主要的逻辑部分就在 KeyGen ...

  8. 大型互联网公司分布式ID方案总结

    ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并 ...

  9. 【selenium】- webdriver常见api

    本文由小编根据慕课网视频亲自整理,转载请注明出处和作者. 1.常见API 2.打开网址 3.操作浏览器 quit()没有完全关闭进程,依旧占用资源. 4.输入框操作 5.选择框操作 6.特殊窗口操作 ...

  10. CodeForces 1082 G Petya and Graph 最大权闭合子图。

    题目传送门 题意:现在有一个图,选择一条边,会把边的2个顶点也选起来,最后会的到一个边的集合 和一个点的集合 , 求边的集合 - 点的集合最大是多少. 题解:裸的最大权闭合子图. 代码: #inclu ...