2012-09-25 66 views
2

我使用vb6應用程序的WM_COPYDATA發送數據到delphi應用程序。在我的系統中,本地是英文,我正確接收數據,但在另一個帶荷蘭本地的系統上,接收文本是亂碼。從vb6到delphi的WM_COPYDATA Sendmessage是亂碼

接收應用程序是德爾福,代碼

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData); 
var 
    copyDataType: TCopyDataType; 
begin 
    copyDataType := TCopyDataType(Msg.CopyDataStruct.dwData); 

    //Handle of the Sender 
    mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From])); 

    case copyDataType of 
    cdtString: HandleCopyDataString(Msg.CopyDataStruct); 
    end; 

    //Send something back 
    msg.Result := mmoResult.Lines.Count; 
end; 

procedure TReceiverMainForm.HandleCopyDataString(
    copyDataStruct: PCopyDataStruct); 
var 
    s: string; 
begin 
    s := PChar(copyDataStruct.lpData); 
    mmoResult.Lines.Add(s); 
end; 

編輯

這裏是發送數據VB6的代碼,數據正在發送的字符串

Dim buf() As Byte 
ReDim buf(1 To LenB(Message)) 
Call CopyMemory(buf(1), ByVal Message, Len(Message)) 
cds.dwData = 0 
cds.cbData = Len(Message) + 1 
cds.lpData = VarPtr(buf(1)) 
' Send the string. 
Dim i As Long 
i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds) 

誰能告訴我做錯了什麼?

+1

您是如何發送數據的?根據你使用的Delphi版本,字符串可以被解釋爲unicode或ANSI。如果你可以確認你的VB代碼發送方法和Delphi版本,我可以做一個合適的答案。 – Deanna

+0

@Deanna,它有Delphi 7標記,所以你距離一半更近一些;-) – TLama

+0

我看到這意味着它正在進行ANSI轉換。在我可以給出明確答案之前,我仍然需要知道VB6代碼。 [D7似​​乎支持寬字符,但用戶界面不](http://stackoverflow.com/a/2281327/588306)。 – Deanna

回答

3

VB字符串基於COM BSTR字符串類型,就像Delphi的WideString字符串類型一樣。 A BSTR是UTF-16編碼的Unicode字符串。 LenB()返回轉換爲本地機器當前語言環境時VB字符串佔用的字節數。你沒有考慮到這一點。您沒有正確地將字符串字節複製到緩衝區中,並且您也沒有將cds.cbData字段設置爲正確的值。 Len()返回String中的UTF-16編碼字符數,而LenB()則返回字節數。對於英文字符串,Len()LenB()將返回相同的值,但對於不能保證的foriegn語言。

我建議您原樣發送原始的VB Unicode編碼數據,並更改您的Delphi代碼以將輸入數據視爲Unicode而不是Ansi,就像它當前正在做的那樣(PChar是Delphi 7中的Ansi,但是是Unicode中的Delphi 2009+)。

您還需要爲cds.dwData字段指定一個唯一值。 VCL使用WM_COPYDATA來處理一些自己的內部數據,因此您必須區分您的WM_COPYDATA消息和VCL的消息。

試試這個:

cds.dwData = RegisterWindowMessage("MyWMCopyData") 
If cds.dwData <> 0 Then 
    cds.cbData = Len(Message) * 2 ' characters are 2-bytes each 
    cds.lpData = StrPtr(Message) ' access the string's character buffer directly 
    ' Send the string. 
    Dim i As Long 
    i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds) 
End If 

var 
    uMyWMCopyDataMsg: UINT = 0; 

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData); 
var 
    s: WideString; // you can use UnicodeString in D2009+ 
begin 
    if (uMyWMCopyDataMsg = 0) or (Msg.CopyDataStruct.dwData <> uMyWMCopyDataMsg) then 
    begin 
    inherited; 
    Exit; 
    end; 

    mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From])); 

    SetString(s, PWideChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData div SizeOf(WideChar)); 
    mmoResult.Lines.Add(s); 

    msg.Result := mmoResult.Lines.Count; 
end; 

initialization 
    uMyWMCopyDataMsg := RegisterWindowMessage('MyWMCopyData'); 
+0

我不明白它是如何處理英文字符串的,BSTR中的字符總是2個字節,不是嗎? –

+0

是的,一個'BSTR'字符是2個字節。然而,在VB中,傳遞字符串「ByVal」將其轉換爲Ansi以與基於'char'的API兼容。因此,在調用'CopyMemory()'時,代碼將源字符串轉換爲Ansi,但它使用Len()而不是LenB()作爲第三個參數。這隻適用於單字節語言,如英語和基於Latin1的語言。 –

+0

謝謝。但是這仍然不應該成爲問題的一部分,因爲除了遠東語言之外,所有的ansi字符集都是單個字節。據我所知,荷蘭人使用拉丁-1(勝利-1252)。 –