Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过WM_COPYDATA在不同Delphi版本应用程序之间传输数据_Delphi_Wm Copydata - Fatal编程技术网

通过WM_COPYDATA在不同Delphi版本应用程序之间传输数据

通过WM_COPYDATA在不同Delphi版本应用程序之间传输数据,delphi,wm-copydata,Delphi,Wm Copydata,我试图让Delphi应用程序通过WM_COPYDATA相互通信。但我遇到的问题是,发送方应用程序是用Delphi7编写的,接收方应用程序是用Delphi10.2编写的。我将我的Delphi7程序的代码复制到Delphi10中,通信工作正常。然而,在Delphi7中使用完全相同的代码导致我的字符串被传递到接收方应用程序,从而损坏。我使用的代码如下: 一个是我的派遣方: procedure TSenderApp.SendString(ToSend: string); var copyDataStr

我试图让Delphi应用程序通过WM_COPYDATA相互通信。但我遇到的问题是,发送方应用程序是用Delphi7编写的,接收方应用程序是用Delphi10.2编写的。我将我的Delphi7程序的代码复制到Delphi10中,通信工作正常。然而,在Delphi7中使用完全相同的代码导致我的字符串被传递到接收方应用程序,从而损坏。我使用的代码如下:

一个是我的派遣方:

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;
在接收方面,我有:

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;
过程TRecieverApp.WMCopyData(var消息:TMessage);
变量
p:PCopyDataStruct;
l:整数;
s:字符串;
开始
p:=PCopyDataStruct(Message.lParam);
如果(p为零)那么
开始
ShowMessage('newmessagereceived!');
l:=p^.cbData;
设定长度(s,(l+1));
StrLCopy(PChar(s),PChar(p^.lpData),l);
Edit1.Text:=s;
结束
其他的
Edit1.Text:=“错误”;
结束;

我做错了什么?或者,为什么从Delphi 7编写的SenderApp而不是Delphi 10编写的SenderApp发送消息时,消息字符串会损坏?

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

您正在使用
Char
的本机编码发送和处理数据,该编码在Delphi 7中为
AnsiChar
,但在Delphi 10.2 Tokyo中为
WideChar
(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}
变量
MyDataID:UINT=0;
过程TRecieverApp.WMCopyData(变量消息:TMessage);
变量
p:PCopyDataStruct;
s:UTF8String;
开始
p:=PCopyDataStruct(Message.lParam);
如果(p nil)和(MyDataID 0)和(p^.dwData=MyDataID),则
开始
集合字符串(s、PAnsiChar(p^.lpData)、p^.cbData);
{$IF CompilerVersion>=20}//D2009+
Edit1.Text:=字符串;
{$ELSE}
Edit1.Text:=utf8解码;
{$IFEND}
ShowMessage('收到新消息!');
结束其他
继承;
结束;
初始化
MyDataID:=RegisterWindowMessage('MyDataID');

最好使用UTF-16的
WideChar
发送数据,或使用UTF-8的
AnsiChar
发送数据。不要使用ANSI。@RemyLebeau,谢谢你,同时也解决了这个问题,但不知道如何转换数据。你需要取消对
Move()
第一个参数中传递的指针的引用,并删除第二个参数中的
@
Move(PAnsiChar(p^.lpData)^,S[1],l)
。另外,您的
cbData
值已经包含空终止符,因此不需要在接收方使用
+1
。如果有的话,您应该使用
-1
忽略空终止符。或者更好,只是根本不发送空终止符,您不需要it@RemyLebeau让它工作,谢谢你的投入。