利用消息机制实现VC与Delphi之间的通讯(发送自定义消息)

时间:2021-12-24 06:49:37

摘要: 本文介绍了使用Windows消息机制实现由不同语言编制的程序之间的相互通讯、联系,并以当前较为流行的两种语言Microsoft Visual C++ 6.0和Borland delphi 5.0为对象,用这两种语言各编制一应用程序,并能很好的通过消息进行交互。 

  关键字:vc++、delphi、消息

  一、 引言

  编制较大型的程序往往需要将一个项目分割成若干个模块,由若干个开发小组共同完成。笔者曾参加过几个大型项目的研发工作,根据需要往往要将项目分为解为几大部分,分到三、四家科研单位共同完成,由于各单位较分散,彼此之间的协调只能根据预先制定好的接口协议来完成,即每个单位同其他单位的程序之间的交互只通过几个接口来完成。而且各单位采用的开发语言也不同,这就为使这些不同语言的程序之间的交互增加了困难。笔者根据实际工作摸索出一些解决上述问题的一些方法,下面就对此作些介绍。

  二、 程序设计思路

  虽然各个单位采取不同的开发语言,从Microsoft Visual C++ 6.0到Borland delphi 5.0乃至Microsoft Visual Basic 6.0,但有一点是相同的:都是工作于Win 32操作系统下的。而Win 32操作系统有一个很重要的机制--消息。我们可以用Microsoft Visual Studio 6.0附带的DDE Spy工具去拦截运行于Windows操作系统下的应用程序所发出的各种消息,而不管这些应用程序是使用何种语言编制的。所以我们可以明确一点:即只要捕获到目标程序的窗口句柄,就能向其发送消息,并可附带两个消息参数将信息传递过去。而用于发送消息的两个函数PostMessage和SendMessage在定义上也很好的体现了这一点:

BOOL PostMessage( HWND hWnd, // 目标窗口句柄
UINT Msg, //发送的消息 
WPARAM wParam, // 第一个消息参数
LPARAM lParam // 第二个消息参数);

BOOL SendMessage( HWND hWnd, // 目标窗口句柄
UINT Msg, //发送的消息 
WPARAM wParam, // 第一个消息参数
LPARAM lParam // 第二个消息参数);
 


  可以看出,从原理上采用消息是可以沟通两个由不同语言编制的程序的,下面通过两个分别由Microsoft Visual C++ 6.0和Borland delphi 5.0编制的模拟程序来简要介绍一下该方法的实现过程。

  三、 由Borland delphi 5.0编制的模拟程序的实现

  新建一个工程,由于在Microsoft Visual C++ 6.0下要捕获其他应用程序的窗口句柄要通过API函数FindWindow(……)来实现,而此函数是根据目标窗口的窗口标题来判断是哪个窗口的,所以要保证两种语言编制的程序能可靠的通信,必须要保证各自窗口标题不发生改变。所以在本程序中需要通过修改窗口的属性来改变窗体的标题,将其设为"delphi消息接收、发送程序"。

  在Borland delphi 5.0下向Microsoft Visual C++ 6.0发送消息比较简单,只须调用Win32 API函数findwindow(……)在当前的所有的窗口中根据对方程序窗体的标题进行搜寻即可。当获取到对方程序的窗口句柄后可以用postmessage(……)或是sendmessage(……)函数对其发送消息了,需要说明的是这两个函数虽然都是向指定窗口发送消息,但前者是"邮递"性质,只要把消息发出去了就算干完了,而不关心对方接收到消息后是否处理;而后者却是一直等待对方把消息处理完,如若对方不处理该消息,那么sendmessage(……)函数也不会返回。虽然差别很细微,但在实际应用中如能选取恰当的消息发送函数,往往会使程序更加完美。发送消息的关键代码如下:

……
{nil参数指定搜寻所有的窗口,捕获窗口标题为"vc消息接收、发送程序"的应用程序的句柄}
hwnd:=findwindow(nil,pchar(’vc消息接收、发送程序’));

postmessage(hwnd,2000,0,1);
……
 


  要响应从Microsoft Visual C++ 6.0发送来的消息,则比较麻烦,首先要添加一个用来描述消息的数据结构,可以定义如下:

type
Tmymessage=record
a:cardinal;
b:integer; 
c:integer; 
d:integer;
end;
 


  在Borland delphi 5.0里响应消息不需要有消息映射,只须象添加一个普通的过程一样,,只是其入口参数必须为刚才所添加的消息结构对象并在其后添加一个消息号即可,比如 procedure receive(var message:Tmymessage);message 2000;在消息响应函数里可以通过判断入口参数的消息结构里的 b、c两数据成员变量来获取随消息发送来的两个消息参数。并根据特定的数值作出相应的反应。 

  四、 由Microsoft Visual C++ 6.0 编制的模拟程序的实现

  在Microsoft Visual C++ 6.0下实现消息发送、响应的设计思路和实现方法与前面提到的方法基本类似,也是将自己的标题固定以便对方获取自己的窗口句柄来向自己发消息,但响应消息时需要靠消息映射来显式实现。

  固定自己的程序窗口标题一般是在工程的应用程序类的初始化函数OnInitial()里作如下修改:

……
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->SetWindowText("vc消息接收、发送程序");
m_pMainWnd->UpdateWindow();
……