用Delphi实现程序间的数据传递

原创 2005年03月03日 11:32:00
用Delphi实现程序间的数据传递
在实际应用中,我们经常需要多个程序相互配合来完成某些特定功能。例如两个应用程序间的同步、互斥;应用程序在起第二份实例时的参数自动传递…。要实现这些功能,就必须能实现程序间的数据传递。

有些特殊的高级技术可在不同的程序间传递数据,如剪贴板、动态数据交换以及OLE自动化,但有条件限制并且相对较复杂。这里,我介绍三种有效的底层技术,希望对编程爱好者有所帮助。
利用WM_COPYDATA消息
使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员:
dwData是一个32位的附加参数
cbData表示要传递的数据区的大小
lpData表示要传递的数据区的指针
下面举个例子。该例子由两个程序构成,分别为SendData和GetData。
SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中。
SendData程序:
var
Form1:TForm1;
implementation
{$R*.DFM}
procedureTForm1.Button1Click(Sender:Tobject);
var
ds:TCopyDataStruct;
hd:Thandle;
begin
ds.cbData:=Length(Edit1.Text)+1;
GetMem(ds.lpData,ds.cbData);//为传递的数据区分配内存
StrCopy(ds.lpData,Pchar(Edit1.Text));
Hd:=FindWindow(nil,'Form2');//获得接受窗口的句柄
ifHd<>0then SendMessage(Hd,WM_COPYDATA,Handle,
Cardinal(@ds))//发送WM_COPYDATA消息
else
ShowMessage('目标窗口没找到!');
FreeMem(ds.lpData);//释放资源
end;

GetData程序:
TForm2=class(Tform)
Edit1:Tedit;
private
{Privatedeclarations}
public
procedureMymessage(vart:TWmCopyData);messageWM_COPYDATA;
{Publicdeclarations}
end;
var
Form2:TForm2;
implementation

procedureTForm2.Mymessage(vart:TWmCopyData);
begin
Edit1.text:=StrPas(t.CopyDataStruct^.lpData);//接受数据并显示。
end;

使用这种方法是WIN32应用程序进行交互的最简单的方法。
使用全局原子
Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一些共享数据。关于对原子的操作,有一组专门的API函数:
GlobalAddAtom在表中增加全局原子
GlobalDeleteAtom在表中删除全局原子
GlobalFindAtom在表中搜索全局原子
GlobalGetAtomName从表中获取全局原子
笔者用这种方法实现了避免程序二次启动,但把第二次启动所带的参数传到第一个实例中以进行相应的处理的程序。基本处理如下:
在工程文件中:
programPvdde;
uses
Forms,shellapi,Windows,dialogs,ddein'dde.pas'{Form1};

{$R*.RES}

begin
ifGlobalFindAtom(Pchar('PDDE_IS_RUNNING'))=0then
//避免二次启动
begin

K:=GlobalAddAtom(Pchar('PDDE_IS_RUNNING'));
Application.Initialize;
Application.CreateForm(TForm1,Form1);
Application.Run;
end
else
begin
//传递二次启动时的参数到第一个实例
H:=FindWindow(Pchar('TForm1'),Pchar('资料保密严禁外传'));
ifParamCount>0then
begin
L:=GlobalAddAtom(Pchar(ParamStr(1)));
ifH<>0then
SendMessage(H,WM_MYMESSAGE,0,L);
{传递原子句柄}

GlobalDeleteAtom(L);{使用后释放}
end;
Application.Terminate;
end;
end.

在相应的窗口单元dde.pas增加对自定义消息WM_MYMESSAGE的处理:

procedureTForm1.MyMessage(varT:Tmessage);
{对WM_MYMESSAGE消息进行处理}

var
P:Array[0..255]ofchar;
begin
GlobalGetAtomName(T.Lparam,P,255);{接受数据到p数组中}
end;

使用存储映象文件
这种方法相对较复杂一些。

当Win95与Winows
Nt向内存中装载文件时,使用了特殊的全局内存区。在该区域内,应用程序的虚拟内存地址和文件中的相应位置一一对应。由于所有进程共享了一个用于存储映象文件的全局内存区域,因而当两个进程装载相同模块(应用程序或DLL文件)时,它们实际可以在内存中共享其执行代码。

笔者通过调用一个带有特殊参数的CreateFileMapping函数,来间接达到程序间共享内存的目的。下面简要解释一下该函数。

HANDLECreateFileMapping(HANDLEhFile,//文件句柄
LPSECURITY_ATTRIBUTESlpFileMappingAttributes,//可选安全属性
DWORDflProtect,//映象文件保护方式
DWORDdwMaximumSizeHigh,//映象文件区域的底值
DWORDdwMaximumSizeLow,//映象文件区域的顶值
LPCTSTRlpName//映象文件的名字);

如果hFile是0xFFFFFFFF,在调用程序中必须指定dwMaximumSizeHigh
和dwMaximumSizeLow参数的值以确定映象文件的大小。通过这样的参数指定,该函数就创建了一个由操作系统页文件支持的特殊逻辑映象文件,而不是由实际操作系统的文件支持的逻辑映象文件。这个逻辑映象文件可以通过复制、继承或者按名字来达到共享。至于其它参数的详细说明,请参看在线帮助。
在建立了映象文件之后,我们可以通过调用另外一个API函数MapViewOfFile来访问它的内存,该函数会返回一个指向共享内存块的特定指针。
LPVOIDMapViewOfFile(
HANDLEhFileMappingObject,//映象文件句柄
DWORDdwDesiredAccess,//访问方式
DWORDdwFileOffsetHigh,//映象文件区域的底值
DWORDdwFileOffsetLow,//映象文件区域的顶值
DWORDdwNumberOfBytesToMap//映射字节数
);
如果dwNumberOfBytesToMap是0,映射整个文件。

以下举例说明:

private
hMapFile:Thandle;
MapFilePointer:Pointer;
public

{Publicdeclarations}
end;

var
Form1:TForm1;
implementation

{$R*.DFM}

procedureTForm1.FormCreate(Sender:Tobject);
begin
hMapFile:=CreateFileMapping(
$FFFFFFFF,//特殊内存映射句柄
nil,page_ReadWrite,0,10000,'DdhDemoMappedFile');//文件名
ifhMapFile<>0then
MapFilePointer:=MapViewOfFile(hMapFile,//上面映象文件的句柄
File_Map_All_Access,0,0,0)//访问整个映象文件
else
ShowMessage('hMapFile=0');
ifMapFilePointer=nilthen
ShowMessage('MapFilePointer=nil');
end;

procedureTForm1.BtnWriteClick(Sender:Tobject);
begin
StrCopy(Pchar(MapFilePointer),
Pchar(EditWrite.Text));//把内容写入共享内存
end;

procedureTForm1.BtnReadClick(Sender:Tobject);
var
S:string;
begin
S:=Pchar(MapFilePointer);//从共享内存读出内容
EditRead.Text:=S;
end;

用这种方法,不但可以在不同的程序之间共享数据,还可以在同一程序的不同实例间共享数据。为了及时通知其它进程共享数据的变化,可以自定义一条用户消息,通过发消息来实现,这里不再赘述。

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

SendMessage和PostMessage发送消息(不同进程传递字符串)

一、函数功能 该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。 ...

Delphi的类与继承

unit Person_Cls; 2 3 interface 4 5 type 6 Person=class //基类 7 private 8 ...

使用package(包功能)实现DLL与主程序的数据库连接共享(Delphi版)

1、使用Package实现 如何使用Delphi开发大型主从架构系统-Package的秘密和威力 相信许多人和我一样,在使用Delphi开发应用系统的时候,一定会想到如何的切割整个应用系统。是把所...
  • pnf88
  • pnf88
  • 2015年02月09日 23:58
  • 1190

Delphi之面向对象的界面复用技术(继承...)

代码复用和界面复用 面向对象的编程思想强调代码的可复用。而Delphi的精髓实际上就是Object Pascal语言,Object Pascal语言是一个非常强大的面向对象的编程语言,可以通过对象的...

DELPHI中自定义消息的发送和接收

DELPHI中的消息处理机制 Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具。由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpasca...
  • xtfnpgy
  • xtfnpgy
  • 2015年07月31日 15:27
  • 1783

Delphi窗体间发送消息或字符串

在Delphi 开发中,常常应用到窗体消息传递,以达成某种操作要求,以下列举一个应用的例子,供大家参考。 自定义过程/函数方法://发送字符串到指字句柄的窗口中 (接收窗体需用发送时的消息常量WM_C...
  • wbryfl
  • wbryfl
  • 2009年07月19日 22:43
  • 5304

应用程序与Service之间通信

实现与Service通信有两种方法,第一种使用bindService()来启动Service; 第二种就是使用startService()启动Service,但是使用BroadCast广播作为信使,...

DELPHI下OPC客户端开发入门

原文:http://www.cnblogs.com/hyd10000/archive/2011/11/07/2240284.html DELPHI下OPC客户端开发入门 一、通信拓扑 根据实际工...

用Delphi编写U盘整盘数据清除程序

由于U盘小巧易携、使用方便、容量适度,使用频度较其他移动存储介质要高,信息安全隐患也要大得多。黑客、病毒和木马都将目标瞄准了移动存储介质特有的“信息安全软肋”,目前移动存储介质的摆渡、木马、远程控制程...
  • fjwolf
  • fjwolf
  • 2012年04月28日 01:06
  • 1133
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用Delphi实现程序间的数据传递
举报原因:
原因补充:

(最多只允许输入30个字)