使用WM_COPYDATA进行通讯

公共单元,定义server 与client类

unit IPC;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
const
  {定义消息常量}
  IPCServerDisconnecting = 'IPCServerDisconnecting';
  IPCClientDisconnecting = 'IPCClientDisconnecting';
  IPCConnectRequest = 'IPCConnectRequest';
  IPCConnectRespose = 'IPCConnectRespose';
type
  {定义事件类型}
  TOnData = procedure(MsgPointer: Pointer) of object; //数据事件
  TOnClientData = procedure(MsgPointer: Pointer; AHwnd: HWND) of object; //当客户端接收数据事件
  TOnConnect = procedure(AHwnd: HWND) of object; //连接事件
  TOnDisconnect = procedure(AHwnd: HWND) of object; //断开事件


  {定义TIPCServer服务器类}
  TIPCServer = class(TComponent)
  private
    FWinHwnd: HWND; //窗体句柄
    FOnClientData: TOnClientData; //当接收到客户端数据时
    FOnConnect: TOnConnect; //当连接
    FOnDisconnect: TOnDisconnect; //当断开
    FActive: Boolean; //是否激活
    FSessionName: string; //连接会话的名字
    FSessionHandle: Longint; //连接会话的消息标识符
    FServerDisconnectHwnd: Longword; //IPCServerDisconnecting消息标识符
    FConnectRequestHwnd: Longword; //IPCConnectRequest消息标识符
    FConnectResposeHwnd: Longword; //IPCConnectRespose消息标识符
    FClientDisconnectHwnd: Longword; //IPCClientDisconnecting消息标识符
    FOnAfterClose: TNotifyEvent; //打开事件
    FOnAfterOpen: TNotifyEvent; //关闭事件
  protected
    procedure WndProc(var AMsg: TMessage);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SendMsg(MsgPointer: Pointer; AWinHwnd: HWND; ASize: DWORD);
    procedure Open;
    procedure Close;
  published
    property Active: Boolean read FActive default False;
    property OnClientData: TOnClientData read FOnClientData write FOnClientData;
    property OnConnect: TOnConnect read FOnConnect write FOnConnect;
    property OnDisconnect: TOnDisconnect read FOnDisconnect write FOnDisconnect;
    property OnAfterClose: TNotifyEvent read FOnAfterClose write FOnAfterClose;
    property OnAfterOpen: TNotifyEvent read FOnAfterOpen write FOnAfterOpen;
    property SessionName: string read FSessionName write FSessionName;
  end;
  {定义客户端TIPCClient}
  TIPCClient = class(TComponent)
  private
    FWinHwnd: HWND; //窗体句柄
    FServerWinHwnd: HWND; //窗体句柄
    FOnData: TOnData; //当客户端接受数据
    FOnConnect: TOnConnect; //当客户端连接
    FOnDisconnect: TOnDisconnect; //当客户端断开连接
    FActive: Boolean; //是否激活
    FSessionName: string; // 连接会话的名字
    FSessionHandle: Longint; //连接会话的消息标识符
    FServerDisconnectHwnd: Longword; //IPCServerDisconnecting消息标识符
    FConnectRequestHwnd: Longword; //IPCConnectRequest消息标识符
    FConnectResposeHwnd: Longword; //IPCConnectRespose消息标识符
    FClientDisconnectHwnd: Longword; //IPCClientDisconnecting消息标识符
  protected
    procedure WndProc(var AMsg: TMessage);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SendMsg(MsgPointer: Pointer; ASize: DWORD);
    procedure Open;
    procedure Close;
  published
    property Active: Boolean read FActive default False;
    property OnData: TOnData read FOnData write FOnData;
    property OnConnect: TOnConnect read FOnConnect write FOnConnect;
    property OnDisconnect: TOnDisconnect read FOnDisconnect write FOnDisconnect;
    property SessionName: string read FSessionName write FSessionName;
  end;


implementation


//TIPCServer实现


constructor TIPCServer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FWinHwnd := 0;
  FSessionHandle := 0;
  //注册消息常量
  FServerDisconnectHwnd := RegisterWindowMessage(IPCServerDisconnecting);
  FConnectRequestHwnd := RegisterWindowMessage(IPCConnectRequest);
  FConnectResposeHwnd := RegisterWindowMessage(IPCConnectRespose);
  FClientDisConnectHwnd := RegisterWindowMessage(IPCClientDisconnecting);
end;


destructor TIPCServer.Destroy;
begin
  if FWinHwnd <> 0 then
  begin
    //广播服务器断开消息
    SendMessage(HWND_BROADCAST, FServerDisconnectHwnd, FWinHwnd, 0);
    DeallocateHWND(FWinHwnd);
  end;
  inherited Destroy;
end;


procedure TIPCServer.Open;
begin
  if not FActive then
  begin
    //注册连接会话的消息标识符
    FSessionHandle := RegisterWindowMessage(PChar(FSessionName));
    //创建新窗体,窗体过程执行WndProc;
    FWinHwnd := AllocateHWND(WndProc);
    if FWinHwnd <> 0 then
    begin
      FActive := True;
      if Assigned(FOnAfterOpen) then
        FOnAfterOpen(Self);
    end
    else
      raise Exception.Create('Cannot Allocate Window Handle');
  end;
end;


procedure TIPCServer.Close;
begin
  if FActive then
  begin
    if FWinHwnd <> 0 then
    begin
      //广播服务器断开的消息
      SendMessage(HWND_BROADCAST, FServerDisconnectHwnd, FWinHwnd, FSessionHandle);
      //释放由AllocateHWND创建的窗体
      DeallocateHWND(FWinHwnd);
      FWinHwnd := 0;
      FActive := False;
      if Assigned(FOnAfterClose) then
        FOnAfterClose(Self);
    end;
  end;
end;


//重载消息处理过程


procedure TIPCServer.WndProc(var AMsg: TMessage);
var
  MsgPointer: Pointer;
  ClientHwnd: HWND;
begin
  //根据消息种类,分别处理
  if ((AMsg.Msg = WM_COPYDATA) and (AMsg.wParam = FSessionHandle)) then
  begin
  //如果是WM_CopyData消息
    MsgPointer := (TCopyDataStruct(Pointer(AMsg.lParam)^)).lpData;
    ClientHwnd := (TCopyDataStruct(Pointer(AMsg.lParam)^)).dwData;
    if Assigned(FOnClientData) then
      FOnClientData(MsgPointer, ClientHwnd);
  end
  else if ((AMsg.Msg = FConnectRequestHwnd) and (AMsg.lParam = FSessionHandle)) then
  begin
  //如果是客户端连接请求消息时
    if FActive then
    begin
      //得到客户端窗口句柄
      ClientHwnd := AMsg.wParam;
      if ClientHwnd <> 0 then
      begin
        SendMessage(ClientHwnd, FConnectResposeHwnd, FWinHwnd, 0);
        if Assigned(FOnConnect) then
          FOnConnect(ClientHwnd);
      end;
    end;
  end
  else if ((AMsg.Msg = FClientDisconnectHwnd) and (AMsg.lparam = FSessionHandle)) then
  begin
    //如果是客户端断开连接时
    ClientHwnd := Amsg.WParam;
    SendMessage(ClientHwnd, FServerDisconnectHwnd, FwinHwnd, 0);
    if Assigned(FOnDisConnect) then
      FOnDisConnect(clientHwnd);
  end;
end;


procedure TIPCServer.SendMsg(MsgPointer: Pointer; AWinHwnd: HWND; ASize: DWORD);
var
  CopyDataStruct: TCopyDataStruct;
begin
  CopyDataStruct.dwData := 0;
  CopyDataStruct.cbData := ASize;
  CopyDataStruct.lpData := MsgPointer;
  SendMessage(AWinHwnd, WM_COPYDATA, FSessionHandle, lParam(@CopyDataStruct));
end;


//TIPCClient实现


constructor TIPCClient.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FWinHwnd := 0;
  FServerWinHwnd := 0;
  FSessionHandle := 0;
  //注册消息常量
  FServerDisconnectHwnd := RegisterWindowMessage(IPCServerDisconnecting);
  FConnectRequestHwnd := RegisterWindowMessage(IPCConnectRequest);
  FConnectResposeHwnd := RegisterWindowMessage(IPCConnectRespose);
  FClientDisconnectHwnd := RegisterWindowMessage(IPCClientDisconnecting);
end;


destructor TIPCClient.Destroy;
begin
  if FWinHwnd <> 0 then
  //释放由AllocateHWND创建的窗体
    DeallocateHWND(FWinHwnd);
  inherited Destroy;
end;


procedure TIPCClient.Open;
begin
  if not FActive then
  begin
    //注册连接会话的消息标识符
    FSessionHandle := RegisterWindowMessage(PChar(FSessionName));
   //创建新窗体,窗体过程执行WndProc;
    FWinHwnd := AllocateHWND(WndProc);
    if FWinHwnd <> 0 then
      SendMessage(HWND_BROADCAST, FConnectRequestHwnd, FWinHwnd, FSessionHandle);
  end;
end;


procedure TIPCClient.Close;
begin
  if FActive then
  begin
    if FWinHwnd <> 0 then
    begin
      //广播消息,客户端断开
      SendMessage(HWND_BROADCAST, FClientDisconnectHwnd, FWinHwnd, FSessionHandle);
     //释放由AllocateHWND创建的窗体
      DeallocateHWND(FWinHwnd);
      FWinHwnd := 0;
      FActive := False;
    end;
  end;
end;


procedure TIPCClient.WndProc(var AMsg: TMessage);
var
  MsgPointer: Pointer;
begin
  //根据消息种类,分别执行
  //WM_CopyData消息
  if (AMsg.Msg = WM_COPYDATA) then
  begin
    MsgPointer := (TCopyDataStruct(Pointer(AMsg.lParam)^)).lpData;
    if Assigned(FOnData) then
      FOnData(MsgPointer);
  end
  //连接响应消息
  else if AMsg.Msg = FConnectResposeHwnd then
  begin
    if not FActive then
    begin
      FServerWinHwnd := AMsg.wParam;
      if Assigned(FOnConnect) then
        FOnConnect(FServerWinHwnd);
      FActive := True;
    end;
  end
  //服务器端断开连接消息
  else if AMsg.Msg = FServerDisconnectHwnd then
  begin
    if FActive then
    begin
      if AMsg.wParam = Longint(FServerWinHwnd) then
      begin
        if Assigned(FOnDisconnect) then
          FOnDisconnect(FServerWinHwnd);
        FServerWinHwnd := 0;
        FActive := False;
      end;
    end;
  end;
end;


procedure TIPCClient.SendMsg(MsgPointer: Pointer; ASize: DWORD);
var
  CopyDataStruct: TCopyDataStruct;
begin
  if FServerWinHwnd <> 0 then
  begin
    CopyDataStruct.dwData := FWinHwnd;
    CopyDataStruct.cbData := ASize;
    CopyDataStruct.lpData := MsgPointer;
    SendMessage(FServerWinHwnd, WM_COPYDATA, FSessionHandle, lParam(@CopyDataStruct));
  end;
end;


end.


server端代码

unit ServerMain;


interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, IPC, ComCtrls, Spin;


type
  TfrmServer = class(TForm)
    Label6: TLabel;
    edtSessionName: TEdit;
    btnListen: TButton;
    GroupBox1: TGroupBox;
    Label3: TLabel;
    Label4: TLabel;
    edtReceiveString: TEdit;
    sedtReceiveInteger: TSpinEdit;
    StatusBar: TStatusBar;
    Label5: TLabel;
    GroupBox2: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    edtSendString: TEdit;
    sedtSendInteger: TSpinEdit;
    btnSend: TButton;
    procedure btnSendClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnListenClick(Sender: TObject);
  private
    FClientHwnd: HWND;
    IPCServer: TIPCServer; //定义IPCServer
    Procedure IPCServerAfterOpen(Sender : Tobject);
    procedure IPCServerConnect(AHwnd: HWND);
    procedure IPCServerDisconnect(AHwnd: HWND);
    procedure IPCServerClientData(MsgPointer: Pointer; AHwnd: HWND);
    procedure IPCServerAfterClose(Sender: TObject);


  public
    { Public declarations }
  end;


type
  {定义一个发送和接收数据记录类型}
  PIPCData = ^TIPCData;
  TIPCData = record
    SendString: string[30];
    SendInteger: integer;
  end;
var
  frmServer: TfrmServer;


implementation


{$R *.DFM}


//当窗体被创建时
procedure TfrmServer.FormCreate(Sender: TObject);
begin
//创建IPCServer
  IPCServer := TIPCServer.Create(self);
  IPCServer.OnAfterOpen := IPCServerAfterOpen;
  IPCServer.OnConnect := IPCServerConnect;
  IPCServer.OnDisconnect := IPCServerDisConnect;
  IPCServer.OnAfterClose := IPCServerAfterClose;
  IPCServer.OnClientData := IPCServerClientData;
end;


//监听连接
procedure TfrmServer.btnListenClick(Sender: TObject);
begin
  if not IPCServer.Active then
    IPCServer.SessionName := edtSessionName.Text;
  IPCServer.Open;
end;




//发送数据
procedure TfrmServer.btnSendClick(Sender: TObject);
var
  MsgData: TIPCData;
begin
  if IPCServer.Active then
  begin
    MsgData.SendString := edtSendString.Text;
    MsgData.SendInteger := SedtSendInteger.Value;
    IPCServer.SendMsg(@MsgData, FClientHwnd, Sizeof(MsgData));
  end;
end;


//服务器连接事件
procedure TfrmServer.IPCServerConnect(AHwnd: HWND);
begin
  FClientHwnd := AHwnd;
  statusbar.Panels[0].Text := '连接状态:已连接';
  statusbar.Refresh;
end;


//服务器断开事件
procedure TfrmServer.IPCServerDisconnect(AHwnd: HWND);
begin
  statusbar.Panels[0].Text := '连接状态:未连接';
  statusbar.Refresh;


end;


//接收客户端数据
procedure TfrmServer.IPCServerClientData(MsgPointer: Pointer; AHwnd: HWND);
var
  AMsg: TIPCData;
begin
  FClientHwnd := AHwnd;
  AMsg := TIPCData(MsgPointer^);
  edtReceiveString.Text := AMsg.SendString;
  sedtReceiveInteger.Value := AMsg.SendInteger;
end;


//服务器端被打开事件
procedure TfrmServer.IPCServerAfterOpen(sender : TObject);
begin
  statusbar.Panels[0].Text := '连接状态:处于监听状态....';
  statusbar.Refresh;
  FClientHwnd := 0;
end;


//服务器端被断开事件
procedure TfrmServer.IPCServerAfterClose(Sender: TObject);
begin
  statusbar.Panels[0].Text := '连接状态:未连接';
  statusbar.Refresh;
  FClientHwnd := 0;
end;






end.



Client端 代码

unit ClientMain;


interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, IPC, Spin, ComCtrls;


type
  TfrmClient = class(TForm)
    edtSessionName: TEdit;
    btnConnect: TButton;
    GroupBox1: TGroupBox;
    edtReceiveString: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label6: TLabel;
    sedtReceiveInteger: TSpinEdit;
    StatusBar: TStatusBar;
    Label5: TLabel;
    GroupBox2: TGroupBox;
    edtSendString: TEdit;
    sedtSendInteger: TSpinEdit;
    Label1: TLabel;
    Label2: TLabel;
    btnSend: TButton;
    procedure btnSendClick(Sender: TObject);
    procedure btnConnectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    IPCClient: TIPCClient;  //定义IPCClient
    procedure IPCClientConnect(AHwnd: HWND);
    procedure IPCClientDisconnect(AHwnd: HWND);
    procedure IPCClientData(MsgPointer: Pointer);
    { Private declarations }
  public
    { Public declarations }
  end;


type
  {定义一个发送和接收数据记录类型}
  PIPCData = ^TIPCData;
  TIPCData = record
    SendString: string[30];
    SendInteger: integer;
  end;


var
  frmClient: TfrmClient;


implementation


{$R *.DFM}


//主窗体创建事件
procedure TfrmClient.FormCreate(Sender: TObject);
begin
  IPCClient := TIPCClient.Create(self);
  IPCClient.OnConnect := IPCClientConnect;
  IPCClient.OnDisconnect := IPCClientDisConnect;
  IPCClient.OnData := IPCClientData;
end;


//连接或断开服务器
procedure TfrmClient.btnConnectClick(Sender: TObject);
begin
  if btnconnect.Caption = '连接' then
  begin
    if not IPCClient.Active then
      IPCClient.SessionName := edtSessionName.Text;
    IPCClient.Open;
  end
  else
    IPCClient.Close;
end;


//发送数据
procedure TfrmClient.btnSendClick(Sender: TObject);
var
  MsgData: TIPCData;
begin
  if IPCClient.Active then
  begin
    MsgData.SendString := edtSendString.Text;
    MsgData.SendInteger := sedtSendInteger.Value;
    IPCClient.SendMsg(@MsgData, Sizeof(MsgData));
  end;
end;


//连接服务器事件
procedure TfrmClient.IPCClientConnect(AHwnd: HWND);
begin
  Statusbar.Panels[0].Text := '连接状态 :已连接';
  Statusbar.Refresh;
  btnConnect.Caption := '断开连接'
end;


//断开服务器连接事件
procedure TfrmClient.IPCClientDisconnect(AHwnd: HWND);
begin
  Statusbar.Panels[0].Text := '连接状态 :未连接';
  Statusbar.Refresh;
  btnConnect.Caption := '连接'
end;


//接收数据事件
procedure TfrmClient.IPCClientData(MsgPointer: Pointer);
var
  AMsg: TIPCData;
begin
  AMsg := TIPCData(MsgPointer^);
  edtReceiveString.Text := AMsg.SendString;
  sedtReceiveInteger.Value := AMsg.SendInteger;
end;


end.


interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, IPC, Spin, ComCtrls;


type
  TfrmClient = class(TForm)
    edtSessionName: TEdit;
    btnConnect: TButton;
    GroupBox1: TGroupBox;
    edtReceiveString: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label6: TLabel;
    sedtReceiveInteger: TSpinEdit;
    StatusBar: TStatusBar;
    Label5: TLabel;
    GroupBox2: TGroupBox;
    edtSendString: TEdit;
    sedtSendInteger: TSpinEdit;
    Label1: TLabel;
    Label2: TLabel;
    btnSend: TButton;
    procedure btnSendClick(Sender: TObject);
    procedure btnConnectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    IPCClient: TIPCClient;  //定义IPCClient
    procedure IPCClientConnect(AHwnd: HWND);
    procedure IPCClientDisconnect(AHwnd: HWND);
    procedure IPCClientData(MsgPointer: Pointer);
    { Private declarations }
  public
    { Public declarations }
  end;


type
  {定义一个发送和接收数据记录类型}
  PIPCData = ^TIPCData;
  TIPCData = record
    SendString: string[30];
    SendInteger: integer;
  end;


var
  frmClient: TfrmClient;


implementation


{$R *.DFM}


//主窗体创建事件
procedure TfrmClient.FormCreate(Sender: TObject);
begin
  IPCClient := TIPCClient.Create(self);
  IPCClient.OnConnect := IPCClientConnect;
  IPCClient.OnDisconnect := IPCClientDisConnect;
  IPCClient.OnData := IPCClientData;
end;


//连接或断开服务器
procedure TfrmClient.btnConnectClick(Sender: TObject);
begin
  if btnconnect.Caption = '连接' then
  begin
    if not IPCClient.Active then
      IPCClient.SessionName := edtSessionName.Text;
    IPCClient.Open;
  end
  else
    IPCClient.Close;
end;


//发送数据
procedure TfrmClient.btnSendClick(Sender: TObject);
var
  MsgData: TIPCData;
begin
  if IPCClient.Active then
  begin
    MsgData.SendString := edtSendString.Text;
    MsgData.SendInteger := sedtSendInteger.Value;
    IPCClient.SendMsg(@MsgData, Sizeof(MsgData));
  end;
end;


//连接服务器事件
procedure TfrmClient.IPCClientConnect(AHwnd: HWND);
begin
  Statusbar.Panels[0].Text := '连接状态 :已连接';
  Statusbar.Refresh;
  btnConnect.Caption := '断开连接'
end;


//断开服务器连接事件
procedure TfrmClient.IPCClientDisconnect(AHwnd: HWND);
begin
  Statusbar.Panels[0].Text := '连接状态 :未连接';
  Statusbar.Refresh;
  btnConnect.Caption := '连接'
end;


//接收数据事件
procedure TfrmClient.IPCClientData(MsgPointer: Pointer);
var
  AMsg: TIPCData;
begin
  AMsg := TIPCData(MsgPointer^);
  edtReceiveString.Text := AMsg.SendString;
  sedtReceiveInteger.Value := AMsg.SendInteger;
end;


end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蚂蚁_CrkRes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值