Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.08.2012, 10:42   #1
avd
Пользователь
 
Регистрация: 06.06.2010
Сообщений: 79
По умолчанию Передача сообщений между окнами

....
private
message WM_COPYDATA;
....
Код:
// с помощью этой ф. окно Петя передаёт сообщение окну Вовочка
procedure TForm1.SendMess(s: string);
var
  CDS: TCopyDataStruct;
begin
  CDS.dwData := 1000; // Тип команды
  CDS.cbData := length(s) + 1; // Длина передаваемых данных
  getMem(CDS.lpData, CDS.cbData);
  try
    StrPCopy(CDS.lpData, s); // Данные в буфер
    SendMessage(FindWindow(nil, 'Вовочка'), WM_COPYDATA, Handle, integer(@CDS));
  finally
    FreeMem(CDS.lpData, CDS.cbData);
  end;
end;
Код:
// А так Вовочка принимает
procedure TForm1.WMCopyData(var MessageData: TWMCopyData);
begin
  if MessageData.CopyDataStruct.dwData = 1000 then
  begin
    if PChar(MessageData.CopyDataStruct.lpData) = '1' then
    begin
      jvLed1.Status := true; // Зажечь светодиод
    end;
    if PChar(MessageData.CopyDataStruct.lpData) = '2' then
    begin
      jvLed1.Status := false; // Погасить
    end;
  end;
end;
Ф. SendMess вызывается по срабатыванию таймера 2 раза в сек.
Проблема в том, что приём идёт как-то нестабильно, то есть, то нет.
avd вне форума Ответить с цитированием
Старый 29.08.2012, 10:55   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Код:
CDS.cbData := length(s) + 1;
Неа.
Код:
CDS.cbData := length(s) + SizeOf(s)*SizeOf(Char);
Человек_Борща вне форума Ответить с цитированием
Старый 29.08.2012, 11:01   #3
avd
Пользователь
 
Регистрация: 06.06.2010
Сообщений: 79
По умолчанию

С П А С И Б О! З А Р А Б О Т А Л О!
avd вне форума Ответить с цитированием
Старый 29.08.2012, 20:01   #4
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Код:
length(s) + SizeOf(s)*SizeOf(Char);
Боже, что ЭТО?

Должно быть:
Код:
procedure TForm1.SendMess(const s: string);
var
  CDS: TCopyDataStruct;
  Buffer: UTF8String;
begin
  Buffer := UTF8Encode(S);

  CDS.dwData := 1000; // Тип команды

  CDS.cbData := Length(Buffer) + 1; 
  CDS.lpData := Pointer(Buffer);

  SendMessage(FindWindow(nil, 'Вовочка'), WM_COPYDATA, Handle, LParam(@CDS));
end;
Код:
procedure TForm1.WMCopyData(var MessageData: TWMCopyData);
var
  Buffer: UTF8String;
  Data: String;
begin
  if MessageData.CopyDataStruct.dwData = 1000 then
  begin
    Buffer := PAnsiChar(MessageData.CopyDataStruct.lpData);
    Data := UTF8ToString(Buffer);

    if Data = '1' then
      jvLed1.Status := true
    else
    if Data = '2' then
      jvLed1.Status := false; // Погасить
  end;
end;
Ещё лучше:
Код:
procedure TForm1.EnableLED(const AEnable: Boolean);
var
  CDS: TCopyDataStruct;
  Buffer: BOOL;
begin
  Buffer := AEnable;

  CDS.dwData := 1000; // Тип команды

  CDS.cbData := SizeOf(Buffer); 
  CDS.lpData := @Buffer;

  SendMessage(FindWindow(nil, 'Вовочка'), WM_COPYDATA, Handle, LParam(@CDS));
end;
Код:
procedure TForm1.WMCopyData(var MessageData: TWMCopyData);
var
  Buffer: BOOL;
begin
  if MessageData.CopyDataStruct.dwData = 1000 then
  begin
    Buffer := PBOOL(MessageData.CopyDataStruct.lpData)^;

    jvLed1.Status := Buffer;
  end;
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 29.08.2012, 20:57   #5
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Боже, что ЭТО?
И правда, очипятка
Код:
CDS.cbData:=length(s)*SizeOf(Char);
Очевидно, способ решения проблем без чудо конвертирования UTF8.

Последний раз редактировалось Человек_Борща; 29.08.2012 в 21:01.
Человек_Борща вне форума Ответить с цитированием
Старый 29.08.2012, 21:13   #6
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Это верно, но только если речь идёт об обмене данных внутри одной программы (и даже - одного модуля). Как только ты выставляшь обмен данными наружу, то String, Char, PChar - уже "вне закона". Потому что это не настоящие типы, а псевдонимы. И они могут переопределяться. Поэтому простая перекомпиляция может изменить состояние с "работает" на "не работает" и обратно.

Вместо типов с плавающим размером нужно использовать типы с фиксированным размером (AnsiString, AnsiChar, PAnsiChar, UnicodeString, WideChar, PWideChar, UTF8String, WideString). Я использовал UTF-8, но это не принципиально. Можно было и UTF-16. А вот использовать ANSI для внешнего обмена будет уже не такой удачной идеей.

Но в любом случае, главное - не String/Char.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 29.08.2012, 22:27   #7
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Это верно, но только если речь идёт об обмене данных внутри одной программы (и даже - одного модуля).
аналогично проблеме передаче строк между DLL и процессом?
Человек_Борща вне форума Ответить с цитированием
Старый 29.08.2012, 22:36   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Примерно да. В обоих случаях при обмене обе стороны должны использовать компиляторно-независимый формат данных.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 29.08.2012, 22:48   #9
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

GunSmoker, значит и в C++ оно тоже актульно?
Человек_Борща вне форума Ответить с цитированием
Старый 29.08.2012, 22:53   #10
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Разумеется. К примеру, _TCHAR (аналог Char в Delphi) - это маппинг или на char (аналог AnsiChar в Delphi) или на wchar_t (аналог WideChar в Delphi).
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переходы между окнами Ark Общие вопросы Delphi 5 22.04.2009 00:22
Как сделать так, чтобы переключение между окнами было автоматическим? barand Свободное общение 9 07.07.2008 23:54
Копирование файлов и каталогов перетаскиваением между двумя окнами SANTA_KLAUD Общие вопросы Delphi 3 28.05.2008 21:52
Передача данных между окнами/приложениями? Dexer Win Api 11 23.05.2007 16:23
Как запретить переход между диалоговыми окнами. dnkR Общие вопросы Delphi 1 18.01.2007 06:59