На использование сообщения налагаются следующие ограничения:
• данные, которые будут приняты, должны быть только для чтения, так как изменение структуры с данными может привести к непредсказуемым последствиям;
• если приложению, получающему данные, требуется использовать их после возврата из обработчика WMCOPYDATA, оно должно скопировать их в локальный буфер.
Итак, приступим к созданию приложения, демонстрирующего работу WM_COPYDATA Для создания хорошего примера потребуется создать два приложения. Первое будет отправлять данные (например, строку текста), другое приложение будет их получать. На главной форме первого приложения помещаем элемент управления TextBox, в который будет записываться передаваемая строка, и кнопку, нажатие которой инициирует передачу данных. Для второго приложения достаточно элемента для отображения текстовой информации типа Label. Перейдем к рассмотрению исходных текстов созданных приложений.
Мы будет посылать сообщение окну, и сообщений может быть различное количество, поэтому для уникальной идентификации операции введем специальную константу:
const
CMD_SETLABELTEXT = 1; // Задаем ID команды
На форме находится кнопка отправки данных другому приложению, ее обработчик выглядит следующим образом (листинг 8.1).
Листинг 8.1.
Отправка данных другому приложению
procedure TDataSender.bnSendClick(Sender: TObject);
var
CDS: TCopyDataStruct;
begin
//Устанавливаем тип команды
CDS.dwData := CMD_SETLABELTEXT;
//Устанавливаем длину передаваемых данных
CDS.cbData := Length(StringEdit.Text) + 1;
//Выделяем память буфера для передачи данных
GetMem(CDS.lpData, CDS.cbData);
try
//Копируем данные в буфер
StrPCopy(CDS.lpData, StringEdit.Text);
// Отсылаем сообщение в окно с заголовком StringReciever
SendMessage(FindWindow(NIL, \'StringReciever\'),
WM_COPYDATA, Handle, Integer(@CDS));
Finally
//Высвобождаем буфер
FreeMem(CDS.lpData, CDS.cbData);
end;
end;
Подробного комментария данный листинг не требует. Обратите лишь внимание на вызов функции SendMessage, которая использует FindWindow для задания одного из своих параметров. Процедура FindWindow в случае успешного выполнения возвращает HWND окна, заголовок которого задается в параметре этой функции (строка StringReciever из предыдущего примера). Синхронная отправка сообщения WM_COPYDATA с набором данных, которые помещены в структуру CDS, осуществляется вызовом SendMessage.
Рассмотрим второе приложение, которое принимает строку и отображает ее в надписи ( Label). Для начала в блок объявления помещаем обработчик сообщения и объявляем само сообщение WM_COPYDATA:
type
TStringReciever = class(TForm)
LabelStr: TLabel;
private
//Обработчик сообщения WM_COPYDATA
procedure WMCopyData(var MessageData: TWMCopyData);
message WM_COPYDATA;
Как и в случае первого приложения, нам необходима константа, которая будет идентифицировать тип операции:
const
CMD_SETLABELTEXT = 1;
Далее рассмотрим тело функции обработчика сообщения WM_COPYDATA (листинг 8.2).
Листинг 8.2.
Обработка сообщения WM_COPYDATA
procedure TStringReciever.WMCopyData(var MessageData: TWMCopyData);
begin
//Устанавливаем свойства метки, если заданная команда совпа-
дает
if MessageData.CopyDataStruct.dwData = CMD_SETLABELTEXT then
begin
//Устанавливаем текст из полученных данных
LabelStr.Caption := PChar(MessageData.CopyDataStruct.lpData);
MessageData.Result := 1;
end else
MessageData.Result := 0;
end;