I'm trying to move an application from Lazarus to Delphi 10.4. The problem I am having is with WM_COPYDATA.
On the VB.Net application:
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 + 1
SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
On the Delphi side:
WM_COPYDATA :
begin
recvdata := PCopyDataStruct(Message.LParam);
msgtype := recvdata^.dwData;
msglen := recvdata^.cbData;
str := StrPas(PCHAR(Recvdata^.lpData));
The msgtype and msglen are coming across fine, but the str (lpdata) is corrupted. I think this has something to do with Delphi using widechar or ANSI.
What do I need to do on the VB.Net and Delphi 10.4 sides to get them to line up ?
Thanks !
In Delphi 2009 and later,
PChar
is an alias forPWideChar
(16bit UTF-16), but the VB.NET code is sending 8bit ANSI encoded bytes instead. So, you need to usePAnsiChar
instead ofPChar
on the Delphi side (unless you change the VB.NET code to useEncoding.Unicode
instead ofEncoding.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 ifmsg
is aString
(it will ifmsg
is aChar[]
array with a null terminator present). The code is settingcds.cbData = len + 1
as if a null terminator were present. It should instead setcds.cbData = len
. And then, on the Delphi side, you can useSetString()
instead ofStrPas()
to get thePAnsiChar
data into anAnsiString
, which you can then assigned to a nativestring
.Try this:
Once that is working, consider using
Encoding.UTF8
instead ofEncoding.Default
to avoid any potential data loss of non-ASCII characters, sinceEncoding.Default
is a locale-specific and potentially lossy conversion, whereas UTF-8 is a loss-less conversion: