Рассылки сообщений, методы: Dispatch, Perform, Broadcast, NotifyControls, функции Windows API
Рассылка сообщений может быть выполнена несколькими способами.
А) Непосредственный вызов метода сообщения. В этом случае необходимо знать точное имя метода и тип параметра метода-приемника сообщения, как это требуется и при вызове статического метода. Полиморфизм в таких вызовах не проявляется.
procedure TForm1.WMMyCol(var Message: TMessage);
var Pan: TPanel;
begin
Pan:=pointer(Message.Lparam);
Pan.Color:=Message.WParam;
inherited;
end;
тогда
procedure TForm1.Button1Click(Sender: TObject);
begin
if not colordialog1.Execute then exit;
Msg.Msg:=WM_COL;
Msg.LParam:=longint(panel1);
Msg.WParam:=colordialog1.Color;
WMMyCol(Msg);
end;
б) С помощью метода Dispatch можно послать сообщение экземпляру класса полиморфно. Он определен в классе TObject следующим образом:
Dispatch (Var Message); Virtual;
Этому методу передается один нетипизированный Var-параметр, но лучше, чтобы это была запись, первое поле которой имеет тип Cardinal. Метод Dispatch считает значение первого поля номером сообщения (динамическим индексом) и начинает поиск соответствующего обработчика среди методов сообщений класса. Поиск продолжается вверх по цепочке наследования пока не будет найден соответствующий метод, в противном случае будет вызван метод DefaultHandler и обработка сообщения на этом завершится. Метод Dispatch не предусматривает передачу дополнительной информации, которая может понадобиться при отработке сообщения. Однако это можно сделать через другие поля параметра Message, присвоив им нужные значения до вызова метода Dispatch, например следующим образом:
Msg.Msg:=WM_COL;
Msg.LParam:=longint(panel2);
Msg.WParam:=colordialog1.Color;
Dispatch(Msg);
в) С помощью метода Perform многие визуальные компоненты могут посылать сообщения сами себе, минуя систему сообщений Windows. Он определен в классе TControl следующим образом:
Perform(Msg: Cardinal, wParam, lParam: Longlnt): Longlnt;
Этот метод использует первый параметр как номер (индекс) сообщения, которое посылается компоненту, от имени которого он вызывается. Два других параметра могут нести дополнительную информацию в зависимости от сообщения.
Self.Perform(WM_COL,colordialog1.Color,longint(panel3))
г) С помощью метода Broadcast компоненты-контейнеры, наследники класса TWinControl могут посылать радиовещательные сообщения, называемые в литературе также широковещательными, каждому компоненту, владельцем которого они является. Он объявлен в классе TWinControl следующим образом:
Broadcast(Var Message);
К таким компонентам-контейнерам относятся Form, GroupBox, Panel, RadioGroup, PageControl, TabControl и ряд других. Это бывает полезно при посылке одного и того же сообщения группе компонентов, однако это должны быть пользовательские сообщения и компоненты должны на него реагировать, поэтому и компоненты должны быть пользовательскими.
Как и методу Dispatch этому методу передается один нетипизированный Var-параметр, поэтому значения другим полям параметра Message, при необходимости, следует присвоить до вызова метода Broadcast.
Общая последовательность действий для реализации посылки такого сообщения может быть следующая:
д) С помощью метода NotifvControls компоненты-контейнеры, наследники класса TWinControl, могут посылать сообщения, аналогичные сообщениям, посылаемым методом Broadcast. В основном метод предназначен для изменения цвета или шрифта (цвета, размера, имя). Он объявлен в классе TWinControl следующим образом:
NotifyControls (Msg: Word);
Этому методу передается один параметр типа Word, с помощью которого указывается номер (индекс) пользовательского сообщения.
е) Использование функций Windows API (Application Programming Interface — интерфейс прикладного программирования) позволяет приложению посылать сообщения самому себе, другим приложениям Windows или самой Windows. Известно несколько таких функций для посылки сообщений:
SendMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longlnt): Longlnt;
— Посылает срочное (асинхронное) сообщение окну (окнам) и вынуждает обрабатывать его. Ждет окончания обработки сообщения и возвращает полученное в результате обработки сообщения значение, которое должно быть больше 0. В очередь сообщений приложения не попадает и с помощью события OnMessage не обрабатывается.
PostMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longlnt): BOOL;
— Посылает сообщение, которое становится в очередь сообщений и сразу возвращает результат. Если возвращает True — сообщение помещено в очередь окна.
Чаще используется для передачи сообщений между приложениями.
— Wnd — Дескриптор окна, которому передается сообщение.
— Msg — Идентификатор передаваемого сообщения.
— wParam, lParam — Необязательная дополнительная информация.
Sendmessage(self.Handle,WM_COL,colordialog1.Color,longint(panel4));
ж) Для посылки собственного (пользовательского) сообщения между приложениями необходимо предварительно в каждом из них. зарегистрировать это сообщение с помощью функции Windows API:
RegisterWindowMessage(St :PChar): Longlnt;
— Регистрирует сообщение и возвращает его индекс (номер) в диапазоне значений $C000…$FFFF.
Примечания:
— St— строка с завершающим нулем (#0), содержащая уникальное имя
сообщения, которое необходимо зарегистрировать, например так:
Edit1,Text:=IntToStr(RegisterWindowMessage(‘WM_USER1’));
— сообщение остается зарегистрированным лишь до конца текущего сеанса работы Windows.
— Для определения дескриптора окна другого приложения можно воспользоваться функцией Windows API FindWindow:
Var Wnd: THandle; Begin
Wnd:=FindWindow(Nil, ‘MSERV’); // MSER V-имя приложения-сервера
If Wnd<>O Then;
— К сожалению, динамически выделяемые номера нельзя использовать в обработчиках сообщений Delphi, поскольку номер сообщения должен быть
известен при компиляции.
з) Для передачи некоторого объема (буфера) данных между приложениями можно использовать сообщение WM_COPYDATA, определенное в модуле Windows. С помощью параметра wParam можно передать дескриптор окна, посылающего сообщение, для получения ответа, а с помощью параметра IParam другому приложению передается указатель на структуру вида:
PCopyDataStruct=ATCopyDataStruct;
TCopyDataStruct=Packed Record
dwData, cbData: DWord;
lpData: Pointer; End;
В поле dwData можно сохранить 32 разряда необходимой информации для приложения-приемника, в поле необходимо cbData указать размер буфера, на который указывает содержимое поля lpData. Отправка сообщения производится с помощью функции SendMessage.