2017-11-25 315 views
2

我想讓Delphi應用程序通過WM_COPYDATA與其他應用程序進行通信。我遇到的問題是發件人應用程序是用Delphi 7編寫的,而接收器是用Delphi 10.2編寫的。我將Delphi 7程序的代碼複製到了Delphi 10中,並且通信非常完美。然而,在Delphi 7中使用完全相同的代碼卻導致我的字符串被傳遞給接收器應用程序以損壞。是我使用的代碼如下:通過WM_COPYDATA在不同的Delphi版本應用程序之間傳輸數據

一個發送端,我有:

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發送的消息字符串被破壞?

回答

1

兩個Delphi版本之間的區別是字符串格式。在Delphi 2007及更早版本中,string使用ANSI格式的1字節AnsiChar字符。在Delphi 2009及更高版本中,string使用UTF-16格式的2字節WideChar字符。發送時需要將數據轉換爲通用字符編碼。

+1

這將是最好使用'WideChar'用UTF-16發送數據,或使用UTF-8'AnsiChar'。根本不要使用ANSI。 –

+0

@RemyLebeau謝謝你,在此期間計算出來,但不知道如何轉換數據。 –

+0

您需要取消引用您在Move()中第一個參數傳遞的指針,並在第二個參數中刪除「@」:Move(PAnsiChar(p^.lpData)^,S [1],l )'。另外,你的'cbData'值已經包含null結束符,所以你不需要在接收端使用'+ 1'。如果有的話,你應該使用'-1'來忽略空終止符。或者更好的是,根本不發送空終止符,你不需要它 –

6

您正在使用本機編碼Char發送和處理數據,這是在Delphi 7中爲AnsiChar,但在Delphi 10.2 Tokyo(德爾福在D2009中將所有內容切換爲Unicode)都是WideChar。當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'); 
相關問題