2

我试图让 Delphi 应用程序通过 WM_COPYDATA 相互通信。我遇到的问题是发送方应用程序是用 Delphi 7 编写的,而接收方应用程序是用 Delphi 10.2 编写的。我将我的 Delphi 7 程序代码复制到 Delphi 10 中,并且通信运行良好。然而,在 Delphi 7 中使用完全相同的代码导致我的字符串被传递给接收器应用程序被破坏。我使用的代码如下:

我有一个发送方:

procedure TSenderApp.SendString(ToSend: string);
var
 copyDataStruct : TCopyDataStruct;

  receiverHandle : THandle;
   res : integer;
begin
 copyDataStruct.dwData := 140500; //use it to identify the message contents
 copyDataStruct.cbData := (1+ Length(ToSend))* SizeOf(Char) ;
 copyDataStruct.lpData := pchar(ToSend) ;

 receiverHandle := FindWindow(PChar('TRecieverApp'),PChar('RecieverApp')) ;
   if receiverHandle = 0 then
   begin
     ShowMessage('CopyData Receiver NOT found!') ;
     Exit;
   end;

   res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), 
   LPARAM(@copyDataStruct)) ;
end;

在接收方,我有:

procedure TRecieverApp.WMCopyData(var Message: TMessage);
var
  p : PCopyDataStruct;
  l : Integer;
  s : string;
begin
  p := PCopyDataStruct( Message.lParam );

  if (p <> nil) then
  begin
  ShowMessage('New Message Recieved!');
    l := p^.cbData;
    SetLength( s, (l+1) );
    StrLCopy( PChar(s), PChar(p^.lpData), l );
    Edit1.Text := s;
  end
  else
    Edit1.Text := 'ERROR';
end;

我究竟做错了什么?或者为什么当从 Delphi 7 编写的 SenderApp 而不是从 Delphi 10 编写的 SenderApp 发送时消息字符串被破坏?

4

2 回答 2

6

您正在使用 的本机编码发送和处理数据,该编码CharAnsiCharDelphi 7 中但WideChar在 Delphi 10.2 Tokyo 中(Delphi 在 D2009 中将所有内容都切换为 Unicode)。当 Delphi 7 以 ANSI 发送数据时,Delphi 10.2 将其误解为 UTF-16。反之亦然。因此,无论哪种方式,您都会以腐败告终。

您需要在发送数据之前将数据转换为约定的字符编码,并在收到数据后将其从该编码转换。

尝试更多类似的东西:

{$IF CompilerVersion >= 24} // XE3+
{$LEGACYIFEND ON} 
{$IFEND}

var
  MyDataID: UINT = 0;

procedure TSenderApp.SendString(const ToSend: string);
var
  copyDataStruct : TCopyDataStruct;
  receiverHandle : HWND;
  res : LRESULT;
  s : UTF8String;
begin
  if MyDataID = 0 then
  begin
    ShowMessage('CopyData ID NOT registered!');
    Exit;
  end;

  receiverHandle := FindWindow('TRecieverApp', 'RecieverApp');
  if receiverHandle = 0 then
  begin
    ShowMessage('CopyData Receiver NOT found!');
    Exit;
  end;

  {$IF CompilerVersion >= 20} // D2009+
  s := UTF8String(ToSend);
  {$ELSE}
  s := UTF8Encode(ToSend);
  {$IFEND}

  copyDataStruct.dwData := MyDataID; //use it to identify the message contents
  copyDataStruct.cbData := Length(s) * SizeOf(AnsiChar);
  copyDataStruct.lpData := PAnsiChar(s);
  res := SendMessage(receiverHandle, WM_COPYDATA, WPARAM(Handle), LPARAM(@copyDataStruct));
end;

initialization
  MyDataID := RegisterWindowMessage('MyDataID');

{$IF CompilerVersion >= 24} // XE3+
{$LEGACYIFEND ON} 
{$IFEND}

var
  MyDataID: UINT = 0;

procedure TRecieverApp.WMCopyData(var Message: TMessage);
var
  p : PCopyDataStruct;
  s : UTF8String;
begin
  p := PCopyDataStruct(Message.lParam);
  if (p <> nil) and (MyDataID <> 0) and (p^.dwData = MyDataID) then
  begin
    SetString(s, PAnsiChar(p^.lpData), p^.cbData);
    {$IF CompilerVersion >= 20} // D2009+
    Edit1.Text := String(s);
    {$ELSE}
    Edit1.Text := UTF8Decode(s);
    {$IFEND} 
    ShowMessage('New Message Received!');
  end else
    inherited;
end;

initialization
  MyDataID := RegisterWindowMessage('MyDataID');
于 2017-11-25T17:44:22.277 回答
1

两个 Delphi 版本之间的区别在于字符串格式。在 Delphi 2007 及更早版本中,string使用 ANSI 格式的 1 字节AnsiChar字符。在 Delphi 2009 及更高版本中,string使用 UTF-16 格式的 2 字节WideChar字符。发送时需要将数据转换为通用字符编码。

于 2017-11-25T15:56:16.180 回答