delphi, передавая параметры выполнения другому экземпляру через wm_copydata, дает неверный результат в Delphi XE2

Этот код раньше работал с Delphi 5, но с delphi XE2 не работает должным образом. Строка, переданная с помощью wm_copydata, будет обрезана.

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;

И в основной форме у меня есть:

procedure TMyAppFormMain.GotMessage_CopyData(var Msg: TWmCopyData);
var
  MsgString: string;
  I: Integer;
begin

  MsgString := PChar(Msg.CopyDataStruct.lpData);
  showmessage(MsgString);


end;

1 ответ

Решение

На самом деле ваш код никогда не был правильным. Это сломано даже на ANSI-версиях Delphi.

Давайте взглянем. Вы готовите сообщение так:

cds.cbData := length(AMsgStr);
cds.lpData := PChar(AMsgStr);

На ANSI Delphi это означает, что текст распределяется до, но не включая нулевого терминатора.

Получатель делает это:

MsgString := PChar(Msg.CopyDataStruct.lpData);

Это зависит от наличия нулевого терминатора. Нет никаких оснований ожидать, что будет и даже пытаться читать дальше cds.cbData байты это ошибка.

Получатель должен заботиться о ценности cds.cbData который отправляется и не читается за пределами буфера.

Теперь другая проблема заключается в том, что вы перешли на Unicode Delphi, поэтому текст теперь в кодировке UTF-16.

Чтобы отправить текст я написал бы:

cds.cbData := length(AMsgStr)*SizeOf(Char);
cds.lpData := PChar(AMsgStr);

А на принимающей стороне это должно быть:

SetString(MsgString, PChar(Msg.CopyDataStruct.lpData), 
  Msg.CopyDataStruct.cbData div SizeOf(Char));

Актерский состав, который вы используете, integer(@cds), это неверно. Которые должны быть LPARAM(@cds),

Другие вопросы по тегам