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

摘要: 本文介绍了使用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();
……

  需要特别说明的是并非在所有的类里都可以添加从其他程序发来消息的响应函数,只有在主框架类里才能接收到外部程序发送来的消息,因为外部程序捕获的句柄只是根据程序标题捕获到的程序主框架的句柄,所以只能将消息发送到主框架类了。自定义消息和消息映射的添加实现情况如下:

  在主框架类的头文件中修改如下片段:

…… 
#define WM_MYMSG 2000
…… 
//{{AFX_MSG(CMainFrame)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
void OnRecvMsg(WPARAM wParam,LPARAM lParam);
DECLARE_MESSAGE_MAP()
……

  再在主框架类的实现文件里修改如下片段:

……
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG_MAP
ON_MESSAGE(WM_TOdelphi,OnRecvMsg)
END_MESSAGE_MAP()
……
void CMainFrame::OnRecvMsg(WPARAM wParam,LPARAM lParam)

  其中,从wParam 传来的参数是接收到的消息附带的第一个参数;从lParam传来的参数是接收到的消息附带的第二个参数。可以通过这两个参数从对方获取更多的附加信息。

  至于向对方发送消息则和前一个程序非常类似,寻找对方窗口可以用Win32 API函数的FindWindow(……),也可以使用MFC的CWnd类的FindWindow(……),后者返回的直接是窗口指针,实现的主要代码如下:

……
//获取以"delphi消息接收、发送程序"为标题的delphi程序的窗口句柄
CWnd *pWnd=CWnd::FindWindow(NULL,"delphi消息接收、发送程序");
//只有当确实捕获到窗口时才向其发送消息,否则会引起异常错误。 
if (pWnd)
pWnd->PostMessage(WM_MYMSG,0,1);
……

  WM_MYMSG是自定义消息,0,1是附带的两个消息参数。具体意义可以通过接口协议自行制定。

  五、 检验程序的交互情况

  首先在各自的编程环境下编译完毕,运行后打开Microsoft Visual Studio 6.0附带的调试工具包DDE Spy,当一个程序从另外一个程序接收到发送来的消息,执行完特定的工作后。可以通过DDE Spy监视到确实是从一个进程发出自定义消息,然后经过Win 32系统的消息队列被另外一个进程所接收并响应。

  结论:

  本程序通过一个简单的例子对在异种语言编制的程序中使用消息作为通讯工具的方法做了简单的介绍,在实际应用中还要考虑许多具体的细节问题,实现起来也要远比本程序烦琐的多。但通过这种方式来解决混合编程中的小数据量的频繁数据通讯无疑是很有优势的。

查看本文来源

http://soft.zhiding.cn/software_zone/2007/1017/560580.shtml

时间: 2024-11-05 01:07:25

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

深入Delphi -- Windows 消息机制

http://www.txsz.net/xs/delphi/3/Windows%20%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6.htm Windows 消息机制 by machine 大家是不是很奇怪为什么我还没说到Delphi的控件呢? 不过不用着急,有关深入控件的内容,将会很快出现了,但在这之前, 还得了解Windows图形界面程序的机制--Windows的消息机制. 使用过Delphi的朋友都知道,Delphi是一个真正面向对象的编程环境, 但是不但如此,De

锻造完美U盘小偷:活用消息机制

锻造完美U盘小偷:活用消息机制作者:灰狐来源:灰狐's Blog 注:本文已发表在<黑客防线>2008年第1期,转载请注明出处. 以前经常看到有人做出一些蛮有意思的小工具,其中最多的似乎就是所谓的U盘小偷了——偷偷地把你U盘里的东西copy出来的东西. 根据以前的<黑客防线>来看,就这一类的工具已经N多了,有脚本或批处理的.有VC的.有BCB的.有delphi或VB的,五花八门:当然其中各个的技术含量也是大不相同,大多数都是采用最常规的做法.注入进程的见过不少,但居然很少有讲使用消

Android线程与消息机制

# 标签: 读博客 UI线程 先从一个经典错误开始: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views 为什么会出现这个错误? UI的呈现必须在同一个线程里面完成. 试想,如果多个线程可以绘制UI,那么肯定乱套,呈现结果不可预期. 因此界面程序必然有一个UI线程,android,ja

android开发系列之消息机制

最近接触到一个比较有挑战性的项目,我发现里面使用大量的消息机制,现在这篇博客我想具体分析一下:android里面的消息到底是什么东西,消息机制到底有什么好处呢? 其实说到android消息机制,我们可能很快就会想到message/handle/looper这三个对象,没错在android里面就是通过此三个对象实现消息机制的.那么我想问的是,为什么我们需要消息机制呢?说到底就是为了更好.更流畅的用户体验,因为在app里面我们或多或少都有可能会设计到一些比较耗时的操作,这个时候如果我们只是一味的将当

Android Handler 消息机制的日常开发运用与代码测试

很多时候我们需要对每个组件或者所有的UI线程要去负责View的创建并且维护它,例如更新冒个TextView的显示,都必须在主 线程中去做,我们不能直接在UI线程中去创建子线程,要利用消息机制:handler 本篇博客将带大家走进我们熟悉的Handler,顺带写了一个例子来验证Handler的消息机制,Handler通过对子线程的处理,实 现对UI的更新等操作 private TextView time; private Handler handler = new Handler(){ publi

【温故Delphi】之VCL消息机制小结

TObject消息分派 procedure Dispatch(var Message); virtual; #负责分派消息到特定VCL组件的事件处理函数 procedure DefaultHandler(var Message); virtual; #消息分类:通过子类覆盖此方法,处理窗口命令消息,窗口标准消息,VCL自行触发消息,VCL通知消息,自定义 VCL封装类的方法种类 procedure WMButtonUp(var Message: TWMButtonUp); message WM_

Windows消息机制详解

消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序. 消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息.例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标.这个记录类型叫做MSG,MSG含有来

Windows消息机制概述

消息是指什么?     消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.    消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息.例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标.这个记录类型叫做MSG,MSG含

MFC框架剖析和消息机制

即便是基于MFC的应用程序,建立窗口类也是会遵循如下的过程: 设计窗口类->注册窗口类->生成窗口->显示窗口->更新窗口->消息循环->消息路由到窗口过程函数处理.下面就剖析一下在MFC中是如何完成上述过程的. (1)每个应用程序都有且仅有一个应用类的全局变量theApp,全局变量先于WinMain函数进行处理. (2)WinMain函数体在APPMODUL.CPP文件中,定义如下: extern "C" int WINAPI _tWinMain(