Delphi 两个应用程序(进程)之间的通信

本文详细介绍使用Delphi实现两个应用程序间的通信,包括注册全局消息、查找窗口句柄及发送和接收消息的具体步骤。通过实例代码展示两种消息通信方式:注册自定义消息和发送WM_COPYDATA消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两个应用程序之间的通信实际上是两个进程之间的通信。由于本人知识有限,决定应用消息来实现。需要用到的知识:

1.RegisterWindowMessage(); //参数类型:pchar;返回值:LongInt;

2.FindWindow(
lpClassName, {窗口的类名}
lpWindowName: PChar {窗口的标题}
): HWND; {返回窗口的句柄; 失败返回 0}

3.Wndproc();//每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam)

4.PostMessage(); //该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。消息队列里的消息通过调用GetMessage和PeekMessage取得。取得后交由WndProc进行处理。

好了,需要的知识都在这里了,现在开始我们的应用程序之间通信。

首先在两个应用程序的主窗体的创建过程注册消息,消息编号一定要不小于WM_USer,然后在程序1中得到程序2的主窗体句柄,并通过PostMessage向其发送消息;接下来在程序2的主窗体创建过程注册和程序1相同编号的消息,然后重载程序2的Wndproc过程。废话就不多说了,直接贴代码:

////////////////////////////////////////////////////////////////////程序1//////////////////////////////////////////////////////////////////////////

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons;

type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Edit1: TEdit;
    procedure FormShow(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
  private
    { Private declarations }
    strWM:Cardinal;
    procedure CallAgent(msg:string);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  h1: HWND;
begin
  h1:= FindWindow(nil,'接收消息窗口');  //发送消息方法一
  PostMessage(h1,strWM,0,0);
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  CallAgent(Edit1.Text);   //发送消息方法二
end;

procedure TForm1.CallAgent(msg: string);
var
  HlAgent:HWND;
  ds:TCopyDatastruct;    //定义一个TCopyDatastruct结构体变量
begin
  ds.cbData := (Length(Msg)+1)*SizeOf(Char); //结构体的第一个元素: 长度cbData
  GetMem(ds.lpData,ds.cbData); //分配内存,结构体的第二个参数:  数据的指针lpDATA
  try
    StrCopy(ds.lpData,PChar(Msg)); //复制值到结构指针
    HlAgent :=FindWindow('TForm2','接收消息窗口');  //查找目标窗体的Handle
    if  HlAgent <> 0 then
    begin
      //ShowMessage('主' + IntToStr(Cardinal(@ds)));
      SendMessage(HlAgent,WM_COPYDATA,0,Cardinal(@ds));   //发送WM_COPYDATA消息,并带上参数 @ds
    end;
  finally
    FreeMem(ds.lpData); //释放数据内存
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  strWM:= RegisterWindowMessage('UserDefMessage');
end;

end.

////////////////////////////////////////////////////////////////////程序2/////////////////////////////////////////////////////////////////////unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

//const
//  My_MousL = WM_USER+100;
type
  TForm2 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    strWM:Cardinal;
  public
    { Public declarations }
    procedure WndProc(var m:TMessage);override;
    procedure MyMessage(var m:TWmCopyData);message WM_CopyData;   //定义一个消息响应过程,并传入一个TWmCopyData的参数
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.FormShow(Sender: TObject);
begin
  strWM := RegisterWindowMessage('UserDefMessage');
end;

procedure TForm2.MyMessage(var m: TWmCopyData);
var
  msg:String;
  pStr:PChar;
begin
  pStr := m.CopyDataStruct^.lpData;
  msg := system.SysUtils.StrPas(pStr);    //获取参数数据
  Edit1.Text := msg;  //显示或者作其他处理
end;

procedure TForm2.WndProc(var m: TMessage);
begin
  if m.Msg = strWM then
    Edit1.Text := Format('得到方式一发送的消息:%d',[m.Msg])
  else
    inherited;
end;

end.

至此,应用程序间通信就完成了,这里需要注意:FindWindow一定要找到你想要得到消息的应用程序,也就是说如果用FindWindow(nil,‘Form2’),你一定得保证窗体的caption:= Form2的程序是唯一的。


另:delphi 进程间通信的两种方法

WIN下面进程间通信的最常用办法就是消息了.

下面记录两种消息通信的方式:

一.第一种办法,利用注册Windows全局的消息.并覆盖wndProc过程来监听消息处理.

  1. 发送消息方:

    private
    strWM:Cardinal; //定义一个局部变量

    proccedure Form1.Create(sender:TObject);
    begin
    strWM:= RegisterWindowMessage(‘newspopMessage’); //注册一个windows全局消息,通过这个消息与其它进程通信
    end;

     ...
     procedure Form1.Button1Click1(Sender:TObject);
     var
         h:Cardinal;
     begin
         //通信的步骤得先找到要通信的信息窗口Handle
         h:=findWindow('目标进程窗口类名','窗口Caption');
         //发送消息消息类型为自定义的strWM
         SendMessage(h,strWM,0,0);  //这里同样可以带参数.wParam,lParam.但我传一个PChar,读取的时候总报错.不知道为啥
        
     end;
    
  2. 接收消息方:

private
strWM:Cardinal; //定义一个局部变量
procedure wndProc(var msg:Tmessage);override; //覆盖这个方法,可以监听所有的Windows消息回调函数

proccedure Form1.Create(sender:TObject);
begin
strWM:= RegisterWindowMessage(‘newspopMessage’); //注册一个windows全局消息,这个相当于暗号
end;
procecure form1.wndProc(var msg:TMessage);
begin
//在这里处理这个消息就行了
showmessage(strpas(PChar(meg.lparam))); //这样写会报错的.但可以处理其它无参数的事情
end;


二.第二种办法,发送一个WM_COPYDATA的消息.并且可以带一个TCopyDataStruct的结构类型参数.

  1. 发送消息方:

    unit Unit1;

    interface

    uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons;

    type
    TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Edit1: TEdit;
    procedure FormShow(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    private
    { Private declarations }
    strWM:Cardinal;
    procedure CallAgent(msg:string);
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.BitBtn1Click(Sender: TObject);
    var
    h1: HWND;
    begin
    h1:= FindWindow(nil,‘接收消息窗口’); //发送消息方法一
    PostMessage(h1,strWM,0,0);
    end;

    procedure TForm1.BitBtn2Click(Sender: TObject);
    begin
    CallAgent(Edit1.Text); //发送消息方法二
    end;

    procedure TForm1.CallAgent(msg: string);
    var
    HlAgent:HWND;
    ds:TCopyDatastruct; //定义一个TCopyDatastruct结构体变量
    begin
    ds.cbData := (Length(Msg)+1)*SizeOf(Char); //结构体的第一个元素: 长度cbData
    GetMem(ds.lpData,ds.cbData); //分配内存,结构体的第二个参数: 数据的指针lpDATA
    try
    StrCopy(ds.lpData,PChar(Msg)); //复制值到结构指针
    HlAgent :=FindWindow(‘TForm2’,‘接收消息窗口’); //查找目标窗体的Handle
    if HlAgent <> 0 then
    begin
    //ShowMessage(‘主’ + IntToStr(Cardinal(@ds)));
    SendMessage(HlAgent,WM_COPYDATA,0,Cardinal(@ds)); //发送WM_COPYDATA消息,并带上参数 @ds
    end;
    finally
    FreeMem(ds.lpData); //释放数据内存
    end;
    end;

    procedure TForm1.FormShow(Sender: TObject);
    begin
    strWM:= RegisterWindowMessage(‘UserDefMessage’);
    end;

    end.

2.接收方程序:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

//const
//  My_MousL = WM_USER+100;
type
  TForm2 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    strWM:Cardinal;
  public
    { Public declarations }
    procedure WndProc(var m:TMessage);override;
    procedure MyMessage(var m:TWmCopyData);message WM_CopyData;   //定义一个消息响应过程,并传入一个TWmCopyData的参数
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.FormShow(Sender: TObject);
begin
  strWM := RegisterWindowMessage('UserDefMessage');
end;

procedure TForm2.MyMessage(var m: TWmCopyData);
var
  msg:String;
  pStr:PChar;
begin
  pStr := m.CopyDataStruct^.lpData;
  msg := system.SysUtils.StrPas(pStr);    //获取参数数据
  Edit1.Text := msg;  //显示或者作其他处理
end;

procedure TForm2.WndProc(var m: TMessage);
begin
  if m.Msg = strWM then
    Edit1.Text := Format('得到方式一发送的消息:%d',[m.Msg])
  else
    inherited;
end;

end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值