Я отправляю следующий запрос приложения С++:
string data_to_send = "Hello World";
PCSTR lpszString = data_to_send.c_str();
COPYDATASTRUCT cds;
cds.dwData = 0; // can be anything
cds.cbData = sizeof(TCHAR) * (data_to_send.size());
cds.lpData = &lpszString;
cout << lpszString << endl;
SendMessage(Output, WM_COPYDATA, (WPARAM)Output, (LPARAM)(PVOID)&cds);
Я получаю структуру, используя следующий код в Delphi
var
p : PCopyDataStruct;
s : UTF8String;
begin
p := PCopyDataStruct(Message.lParam);
if (p <> nil) then
begin
SetString(s, PAnsiChar(p^.lpData), p^.cbData);
ShowMessage(s);
end else
inherited;
end;
Строка выглядит неправильно. В отладчике он равен следующему
'l'#$FE#$F6#2'Hello World'#0#$10#3#$88'u'#$B#0
Мы видим 22 байта с дополнительными 4 байтами перед сообщением. Если мы используем CHAR вместо TCHAR, то видим 11 байт, но опять же со смещением в 4 байта
#$18#$F9#$1B#3'Hello W'
Пожалуйста помоги!!!
Спасибо Реми Лебо за помощь, его код делает все так, как было задумано изначально и Дэвиду Хеффернану за правильное замечание! Они спасли меня. Вот рабочий код.
Отправьте lpszString, а не &lpszString. Также прекратите использовать TCHAR. Вы отправляете массив символов.
@ Дэниел А. Уайт, я согласен с тобой. Отправка сообщений в обратном направлении работает корректно. ToSend := 'Hello World'; s := UTF8String(ToSend); copyDataStruct.dwData := MyDataID; //use it to identify the message contents copyDataStruct.cbData := Length(s) * SizeOf(AnsiChar); copyDataStruct.lpData := PAnsiChar(s); res := SendMessage(receiverHandle, WM_COPYDATA, WPARAM(Handle), LPARAM(@copyDataStruct));
@AgniusIgres После вашего обновления вы теперь отправляете все 1024 chars, хотя вы заполняете только 11 chars. Если вы собираетесь использовать фиксированный массив char[] вместо std::string, рассмотрите возможность использования strlen() для cds.cbData





На стороне С++:
cds.dwData не должен быть равен 0. Используйте более уникальное значение, например результат вызова RegisterWindowMessage(). Многие приложения и даже VCL внутри используют WM_COPYDATA для разных целей, поэтому вы не хотите по ошибке запутаться в чужом сообщении.
sizeof(TCHAR) вместо этого должно быть sizeof(char) (или полностью опущено, поскольку sizeof(char) всегда равно 1).
cds.lpData = &lpszString; должно быть cds.lpData = lpszString; вместо этого. Вы отправляете адрес самой переменной lpszString, а не адрес символьных данных, на которые она указывает. Вот почему вы видите мусор на другом конце — вы видите случайные байты из стека вызовов, где находится lpszString, который в вашем случае включает объект std::string (внутренние члены которого включают буфер оптимизации коротких строк, который почему вы тоже видите своих персонажей).
Со стороны Делфи:
вы должны подтвердить, что p^.dwData является вашим уникальным номером перед дальнейшей обработкой сообщения. Если число не соответствует ожидаемому, передайте сообщение обработчику inherited и продолжайте.
UTF8String должен быть AnsiString, если std::string отправителя на самом деле не закодирован в UTF-8.
Попробуй это:
const UINT uMyDataID = RegisterWindowMessage(TEXT("MyDataID"));
...
if (uMyDataID != 0)
{
string data_to_send = u8"Hello World";
COPYDATASTRUCT cds;
cds.dwData = uMyDataID;
cds.cbData = sizeof(char) * data_to_send.size();
cds.lpData = const_cast<char*>(data_to_send.c_str());
// or: cds.lpData = data_to_send.data(); in C++17 and later
SendMessage(Output, WM_COPYDATA, reinterpret_cast<WPARAM>(Output), reinterpret_cast<LPARAM>(&cds));
}
var
uMyDataID: UINT = 0;
...
procedure TMyForm.WMCopyData(var Message: TMessage);
var
p : PCopyDataStruct;
s : UTF8String;
begin
p := PCopyDataStruct(Message.lParam);
if (uMyDataID <> 0) and (p <> nil) and (p^.dwData = uMyDataID) then
begin
SetString(s, PAnsiChar(p^.lpData), p^.cbData);
ShowMessage(s);
end else
inherited;
end;
...
initialization
uMyDataID := RegisterWindowMessage('MyDataID');
cds.lpData = data_to_send.c_str(); Ошибка компиляции: значение типа "const char *" не может быть присвоено сущности типа "PVOID". Проблема уже решена и пост обновлен, но я добавлю ваши правки по поводу p^.dwData. Большое спасибо!
@AgniusIgres Я уже исправил проблему c_str до того, как вы опубликовали этот комментарий.
Похоже, вы смешиваете строки Unicode и ansi.