This code used to work with Delphi 5, but with delphi XE2 does not work as expected. The string passed using wm_copydata will be cut.
procedure SendAppParameters(aMsgStr: string);
var
hwnd: THandle;
cds: CopyDataStruct;
begin
hwnd := FindWindow('TMyAppFormMain', nil); //<-- Substitute window classname with your own
if hwnd <> 0 then
begin
// showmessage(aMsgStr);
// prepare the data to copy
cds.dwData := 0;
cds.cbData := length(AMsgStr);
cds.lpData := PChar(AMsgStr);
// activate the destination window
SetForegroundWindow(hwnd);
// send the data to the first instance using a wm_CopyData message
SendMessage(hwnd, wm_CopyData, Application.Handle, integer(@cds));
end
end;
And in the Main Form I have:
procedure TMyAppFormMain.GotMessage_CopyData(var Msg: TWmCopyData);
var
MsgString: string;
I: Integer;
begin
MsgString := PChar(Msg.CopyDataStruct.lpData);
showmessage(MsgString);
end;
In fact your code has never been correct. It is broken even on ANSI versions of Delphi.
Let's take a look. You prepare the message like this:
cds.cbData := length(AMsgStr);
cds.lpData := PChar(AMsgStr);
On an ANSI Delphi that means that the text is marshalled up to but not including the null-terminator.
The receiver does this:
MsgString := PChar(Msg.CopyDataStruct.lpData);
This relies on there being a null-terminator present. There's no reason to expect that there would be and even to attempt to read beyond cds.cbData
bytes is an error.
The recipient must take care to heed the value of cds.cbData
that is sent and not read beyond the end of the buffer.
Now, the other issue is that you have moved to a Unicode Delphi and so text is now UTF-16 encoded.
To send the text I would write:
cds.cbData := length(AMsgStr)*SizeOf(Char);
cds.lpData := PChar(AMsgStr);
And on the receiving side it should be:
SetString(MsgString, PChar(Msg.CopyDataStruct.lpData),
Msg.CopyDataStruct.cbData div SizeOf(Char));
The cast that you use, integer(@cds)
, is incorrect. That should be LPARAM(@cds)
.