通过WM_COPYDATA在不同Delphi版本应用程序之间传输数据
我试图让Delphi应用程序通过WM_COPYDATA相互通信。但我遇到的问题是,发送方应用程序是用Delphi7编写的,接收方应用程序是用Delphi10.2编写的。我将我的Delphi7程序的代码复制到Delphi10中,通信工作正常。然而,在Delphi7中使用完全相同的代码导致我的字符串被传递到接收方应用程序,从而损坏。我使用的代码如下: 一个是我的派遣方:通过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
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让它工作,谢谢你的投入。