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,
PCharis an alias forPWideChar(16bit UTF-16), but the VB.NET code is sending 8bit ANSI encoded bytes instead. So, you need to usePAnsiCharinstead ofPCharon the Delphi side (unless you change the VB.NET code to useEncoding.Unicodeinstead 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 ifmsgis aString(it will ifmsgis aChar[]array with a null terminator present). The code is settingcds.cbData = len + 1as 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 thePAnsiChardata into anAnsiString, which you can then assigned to a nativestring.Try this:
Once that is working, consider using
Encoding.UTF8instead ofEncoding.Defaultto avoid any potential data loss of non-ASCII characters, sinceEncoding.Defaultis a locale-specific and potentially lossy conversion, whereas UTF-8 is a loss-less conversion: