Reputation: 5961
i am sending data to a delphi app using WM_COPYDATA from vb6 app. in my system which local is english, i receive the data correctly, but on another system with dutch local, the receive text is garbled.
the receiving app is the delphi, the code is
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;
EDIT
here is the vb6 code that is sending the data, the data am sending is string
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)
can anyone tell me what am doing wrong?
Upvotes: 2
Views: 2684
Reputation: 595762
VB strings are based on the COM BSTR
string type, just like Delphi's WideString
string type is. A BSTR
is a UTF-16 encoded Unicode string. LenB()
returns the number of bytes that a VB string occupies when converted to the local machine's current locale. You are not taking that into account. You are not copying the string bytes into your buffer correctly, and you are not setting the cds.cbData
field to the correct value, either. Len()
returns the number of UTF-16 encoded characters in the String, whereas LenB()
returns the number of bytes instead. For an English string, Len()
and LenB()
will return the same value, but for a foriegn language that is not guaranteed.
I suggest you send the original VB Unicode encoded data as-is, and change your Delphi code to treat the incoming data as Unicode instead of Ansi like it is currently doing (PChar
is Ansi in Delphi 7, but is Unicode in Delphi 2009+).
You also need to assign a unique value to the cds.dwData
field. WM_COPYDATA
is used by the VCL for some of its own internal data, so you have to differentiate between your WM_COPYDATA
messages and the VCL's messages.
Try this instead:
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');
Upvotes: 3