`

DELPHI:实现程序间的数据传递

阅读更多
在实际应用中,我们经常需要多个程序相互配合来完成某些特定功能。例如两个应用程序间的同步、互斥;应用程序在起第二份实例时的参数自动传递…。要实现这些功能,就必须能实现程序间的数据传递。

有些特殊的高级技术可在不同的程序间传递数据,如剪贴板、动态数据交换以及OLE自动化,但有条件限制并且相对较复杂。这里,我介绍三种有效的底层技术,希望对编程爱好者有所帮助。

利用WM_COPYDATA消息
 
使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员:
dwData 是一个32位的附加参数
cbData 表示要传递的数据区的大小
lpData 表示要传递的数据区的指针

下面举个例子。该例子由两个程序构成,分别为SendData和GetData。

SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中。

SendData程序:
……

var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.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'); // 获得接受窗口的句柄
if Hd <> 0 then
SendMessage (Hd, WM_COPYDATA, Handle,
Cardinal(@ds)) // 发送WM_COPYDATA消息
else
ShowMessage ('目标窗口没找到!');
FreeMem (ds.lpData); //释放资源
end;

GetData程序:
 
TForm2 = class(TForm)
Edit1: TEdit;
private
{ Private declarations }
public
procedure Mymessage(var t:TWmCopyData);message WM_COPYDATA;
{ Public declarations }
end;

var
Form2: TForm2;
implementation
procedure TForm2.Mymessage(var t:TWmCopyData);
begin
Edit1.text:=StrPas(t.CopyDataStruct^.lpData);//接受数据并显示。
end;

使用这种方法是WIN32应用程序进行交互的最简单的方法。

使用全局原子
Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一些共享数据。关于对原子的操作,有一组专门的API函数:

GlobalAddAtom 在表中增加全局原子
GlobalDeleteAtom 在表中删除全局原子
GlobalFindAtom 在表中搜索全局原子
GlobalGetAtomName 从表中获取全局原子

笔者用这种方法实现了避免程序二次启动,但把第二次启动所带的参数传到第一个实例中以进行相应的处理的程序。基本处理如下:

在工程文件中:

program Pvdde;
uses
Forms,shellapi,Windows,dialogs,dde in 'dde.pas' {Form1};
{$R *.RES}
begin
if GlobalFindAtom(PChar('PDDE_IS_RUNNING')) = 0 then
//避免二次启动
begin
K:=GlobalAddAtom(PChar('PDDE_IS_RUNNING'));
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end
else
begin

//传递二次启动时的参数到第一个实例

H := FindWindow(PChar('TForm1'), PChar('资料保密 严禁外传'));
if ParamCount > 0 then
begin
L := GlobalAddAtom(PChar(ParamStr(1)));
if H<>0 then
SendMessage(H, WM_MYMESSAGE, 0, L);
{ 传递原子句柄 }
GlobalDeleteAtom(L); { 使用后释放 }
end;

Application.Terminate;
end;
end.

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

procedure TForm1.MyMessage(var T:TMessage);
{对 WM_MYMESSAGE消息进行处理 }
var
P:Array [0..255] of char;
begin
GlobalGetAtomName(T.LParam, P,255); { 接受数据到p数组中 }
。。。

end;

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

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

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

HANDLE CreateFileMapping(
HANDLE hFile, //文件句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 可选安全属性
DWORD flProtect, // 映象文件保护方式
DWORD dwMaximumSizeHigh, // 映象文件区域的底值
DWORD dwMaximumSizeLow, // 映象文件区域的顶值
LPCTSTR lpName // 映象文件的名字
);

如果hFile是0xFFFFFFFF,在调用程序中必须指定dwMaximumSizeHigh 和dwMaximumSizeLow参数的值以确定映象文件的大小。通过这样的参数指定,该函数就创建了一个由操作系统页文件支持的特殊逻辑映象文件,而不是由实际操作系统的文件支持的逻辑映象文件。这个逻辑映象文件可以通过复制、继承或者按名字来达到共享。至于其它参数的详细说明,请参看在线帮助。

在建立了映象文件之后,我们可以通过调用另外一个API函数MapViewOfFile来访问它的内存,该函数会返回一个指向共享内存块的特定指针。

LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 映象文件句柄
DWORD dwDesiredAccess, // 访问方式
DWORD dwFileOffsetHigh, // 映象文件区域的底值
DWORD dwFileOffsetLow, // 映象文件区域的顶值
DWORD dwNumberOfBytesToMap // 映射字节数
);

如果 dwNumberOfBytesToMap 是0,映射整个文件。以下举例说明:

private
hMapfile: THandle;
MapFilePointer: Pointer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
hMapFile := CreateFileMapping (
$FFFFFFFF, // 特殊内存映射句柄
nil, page_ReadWrite, 0,10000,
'DdhDemoMappedFile'); // 文件名
if hMapFile <> 0 then
MapFilePointer := MapViewOfFile (
hMapFile, // 上面映象文件的句柄
File_Map_All_Access,
0, 0, 0) // 访问整个映象文件
else
ShowMessage ('hMapFile = 0');
if MapFilePointer = nil then
ShowMessage ('MapFilePointer = nil');
end;

procedure TForm1.BtnWriteClick(Sender: TObject);
begin
StrCopy (PChar (MapFilePointer),
PChar (EditWrite.Text));//把内容写入共享内存
end;

procedure TForm1.BtnReadClick(Sender: TObject);
var
S: string;
begin
S := PChar (MapFilePointer);//从共享内存读出内容
EditRead.Text := S;
end;

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

利用以上三种方法均可以有效地实现数据传递、共享,所有的例子程序均在Delphi 3.0,4.0下调试通过。如需源码,写信至wj_email@yahoo.com索要 
 
分享到:
评论

相关推荐

    Delphi程序间消息传递.txt

    通过上述实例可以看出,利用`WM_COPYDATA`消息可以轻松地实现在两个不同的Delphi程序之间传递数据。这种方法不仅简单高效,而且避免了共享内存等复杂的通信机制,非常适合于轻量级的数据交换需求。 总之,Delphi...

    多个DELPHI程序间的变量共享

    在DELPHI编程环境中,有时候我们需要在多个程序之间共享数据或变量,这通常是由于应用程序间的协同工作、数据传递或是为了优化资源管理。本教程将深入探讨如何实现多个DELPHI程序间的变量共享。 首先,我们要了解...

    delphi不同窗体的变量传递

    5. **使用接口(Interface)**:接口提供了一种强类型的数据传递方式,可以确保数据在传递过程中不会被误用。一个窗体可以实现一个接口,另一个窗体可以通过这个接口来访问其数据。 6. **使用容器类**:如果多个...

    delphi7两个应用程序间的通信

    本篇文章将详细探讨如何使用Delphi 7实现两个独立的EXE程序间的信息交换。 首先,我们要理解“发送消息”在Windows操作系统中的基本概念。在Windows API中,消息队列是进程间通信(IPC,Inter-Process ...

    delphi多线程传递参数及同步二

    通过以上代码示例,我们可以清楚地了解到如何在 Delphi 中创建多线程、传递参数以及进行线程间的同步。理解这些基本概念和技巧对于编写高效、稳定的多线程应用程序至关重要。在实际项目中,还需要考虑异常处理、资源...

    Delphi的程序间的共享数据代码

    在Delphi编程环境中,开发跨进程的共享数据应用是一个常见的需求...总的来说,通过熟练掌握Windows API和Delphi的PInvoke技术,开发者可以轻松地实现在不同Delphi程序间共享数据的功能,提高应用程序的交互性和灵活性。

    通过串口传递数据的Delphi实现.rar

    在IT行业中,串口通信是一种常见且重要的通信方式,尤其...通过以上步骤,你就可以在Delphi中实现串口数据的传递了。记住,实践是最好的老师,动手尝试编写代码并与实际硬件设备交互,将使你对串口通信有更深入的理解。

    实现消息的传递 delphi7开发

    总结来说,Delphi 7中的消息传递是通过Windows API实现的,结合`TMessage`类和消息处理函数,我们可以创建自定义消息并在不同对象之间传递数据。通过学习和掌握这一机制,开发者能够更好地理解和控制应用程序的内部...

    Delphi 软件程序自动重启

    通过以上步骤,我们便能在Delphi程序中实现自动重启功能。需要注意的是,这种方法适用于需要完全关闭并重新启动应用程序的情况。对于只需要更新某些动态组件而无需完全重启的情况,可能需要其他技术,如模块热替换或...

    在Delphi中利用多线程实现数据采集的方法.doc

    3. **同步机制**:为了保证线程间的正确通信,Delphi提供了多种同步机制,如`Synchronize`函数用于在线程之间安全地传递数据和执行操作。 ##### 具体实例分析 1. **实例背景**:本实例旨在演示如何使用多线程技术...

    Delphi实现参数传递函数的例子.rar

    本示例探讨的是如何在Delphi中实现参数传递函数,这是一种常见且强大的编程技术,尤其在需要进行回调或者事件处理时。下面将详细解释这个知识点。 首先,我们要理解什么是参数传递。在函数调用时,我们可以将数据或...

    delphi 键盘钩子 传递数据

    总结,通过上述步骤,我们了解了如何在Delphi中实现键盘钩子以及如何通过DLL进行数据传递。这种方法对于需要实时监控键盘输入或在特定条件下修改键盘行为的应用程序非常有用。记住,虽然钩子和DLL能提供强大的功能,...

    用DELPHI7.0实现简易聊天室程序

    在本文中,我们将深入探讨如何使用DELPHI 7.0这一经典的编程环境来实现一个简易的聊天室程序。DELPHI 7.0是一款基于Object Pascal语言的集成开发环境,它提供了强大的图形用户界面(GUI)设计工具以及对Windows API...

    Delphi工具主程序调用子窗口(多窗口)

    4. 数据传递,可以使用参数、全局变量或事件机制。 5. 考虑线程安全和程序架构,确保主程序和子窗口的协同工作。 通过以上步骤,开发者可以灵活地构建具有多窗口界面的Delphi应用程序,实现功能的模块化和程序的...

    使用delphi编写进程间内存共享的例子

    在编程领域,进程间通信...总结来说,这个Delphi示例通过内存映射文件实现了进程间的高效数据共享。通过学习和理解这段代码,开发者可以掌握如何在自己的应用程序中运用类似的技术,提升多进程环境下的数据交互性能。

    Delphi聊天小程序

    在这个Delphi聊天小程序中,服务器端扮演着核心角色,它负责接收来自多个客户端的连接请求,并管理这些连接,确保信息在不同客户端间流畅地传递。服务器端通常会使用TCP(传输控制协议)或UDP(用户数据报协议)来...

    delphi DLL及数据共享

    本资源主要探讨了如何在Delphi中创建和使用DLL进行数据共享,这对于开发大型复杂软件系统或多个程序间通信具有重要意义。 1. Delphi中创建DLL: 在Delphi中创建DLL,首先需要创建一个新的项目,并选择“动态链接库...

    通过消息在两个独立程序之间传递参数的Delphi示例源代码

    通过上述步骤,我们已经创建了一个简单的Delphi示例,展示了如何通过消息在两个独立的Delphi程序之间传递参数。这个示例可以帮助开发者理解进程间通信的基本概念,并且可以作为进一步开发更复杂IPC解决方案的基础。...

    Delphi获取Form数据

    在Delphi编程环境中,Form是用户界面的基本组成部分,它包含...通过以上方式,Delphi开发者可以轻松地获取和传递Form上的数据,实现复杂的用户界面交互和程序逻辑。理解这些基础概念对于Delphi应用程序的开发至关重要。

    delphi操作外部程序

    当启动外部程序时,可以通过命令行参数传递数据。在`ShellExecute`中,第二个参数`lpVerb`可以设置为空字符串,第三个参数`lpFile`为程序路径,第四个参数`lpParameters`则用于传递参数。 ```delphi procedure ...

Global site tag (gtag.js) - Google Analytics