In Delphi 2009 and later, PChar
is an alias for PWideChar
(16bit UTF-16), but the VB.NET code is sending 8bit ANSI encoded bytes instead. So, you need to use PAnsiChar
instead of PChar
on the Delphi side (unless you change the VB.NET code to use Encoding.Unicode
instead of Encoding.Default
).
Which BTW, there is a (potential) bug in the VB.NET code. DotNet strings are not null-terminated, so Encoding.GetBytes(msg)
will not output a null terminator byte if msg
is a String
(it will if msg
is a Char[]
array with a null terminator present). The code is setting cds.cbData = len + 1
as if a null terminator were present. It should instead set cds.cbData = len
. And then, on the Delphi side, you can use SetString()
instead of StrPas()
to get the PAnsiChar
data into an AnsiString
, which you can then assigned to a native string
.
Try this:
Dim sarr As Byte() = System.Text.Encoding.[Default].GetBytes(msg)
Dim len As Integer = sarr.Length
Dim cds As COPYDATASTRUCT
cds.dwData = CType(wParam, IntPtr)
cds.lpData = msg
cds.cbData = len
SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
var
...
astr: AnsiString;
str: String;
...
WM_COPYDATA :
begin
recvdata := PCopyDataStruct(Message.LParam);
msgtype := recvdata^.dwData;
msglen := recvdata^.cbData;
SetString(astr, PAnsiChar(Recvdata^.lpData), msglen);
str := string(astr);
...
end;
Once that is working, consider using Encoding.UTF8
instead of Encoding.Default
to avoid any potential data loss of non-ASCII characters, since Encoding.Default
is a locale-specific and potentially lossy conversion, whereas UTF-8 is a loss-less conversion:
Dim sarr As Byte() = System.Text.Encoding.UTF8.GetBytes(msg)
Dim len As Integer = sarr.Length
Dim cds As COPYDATASTRUCT
cds.dwData = CType(wParam, IntPtr)
cds.lpData = msg
cds.cbData = len
SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
var
...
utf8: UTF8String;
str: String;
...
WM_COPYDATA :
begin
recvdata := PCopyDataStruct(Message.LParam);
msgtype := recvdata^.dwData;
msglen := recvdata^.cbData;
SetString(utf8, PAnsiChar(Recvdata^.lpData), msglen);
str := string(utf8);
...
end;