Статьи Королевства Дельфи


Два простых способа уведомления. - часть 2


Объект-клиент должен иметь хэндл окна, который регистрируется на объекте-сервере и обработчик событий этого окна, который будет вызыватся при оповещении сервером списка клиентов (окон).
У объекта-клиента можно поступить двояко. Если объект-клиент уже имеет хэндл окна (например, форма) то пишется обработчик фиксированного номера события: procedure ServMsg(var Msg: TMessage); message WM_NOTIFY_MSG; или если окна нет, то создается универсальный метод-обработчик и невидимое окно при помощи функции AllocateHWND() (пример смотрите в исходниках VCL - объект TTimer)

Прелесть этого метода состоит в том, что объект-клиент может быть вообще в другом приложении, нежели объект-сервер, и такой трюк пройдет при использовании DLL. Кроме того передавать можно не только пару цифр, но и блоки данных (и даже строки) при помощи сообщения WM_COPYDATA.
Но это уже другая история, а мы пока пойдем дальше.

Способ 2. Оповещение через объект-посредник.

В отдельном модуле создаем объект-посредник, который имеет один метод типа SendEvent и одну ссылку на обработчик события OnEvent. Я назвал такой объект TSynaps (да простят меня нейрохирурги) unit Synaps; interface uses Windows, Messages, SysUtils, Classes; type TSynaps = class(TObject) private FOnEvent : TNotifyEvent; public procedure SendEvent; property OnEvent : TNotifyEvent read FOnEvent write FOnEvent; end; implementation procedure SendEvent; begin if Assigned(FOnEvent) then try FOnEvent(Self); except end; end; end; Причем методов и событий может быть много разных на любой вкус. С очередями, асинхронными "прослойками", задержками и другими наворотами. Тут уж кто на что горазд. Я лишь демонстрирую идею. Модуль с объектом-сервером и модуль с объектом-клиентом имеют право знать о модуле Synaps. В объекте-сервере реализуются уже знакомые нам три функции (чуть иначе):
в интерфейсе объекта: procedure RegisterSynaps(Syn: TSynaps); var i: integer; begin i := FSynapsList.IndexOf(pointer(Syn)); if i < 0 then FSynapsList.Add(pointer(Syn)); end; procedure UnregisterSynaps(Syn: TSynaps); var i: integer; begin i := FSynapsList.IndexOf(pointer(Syn)); if i >= 0 then FSynapsList.Delete(i); end; и приватная функция: procedure NotifySynapses; var i: integer; begin i := 0; while i < FSynapsList.Count do begin TSynaps(FSynapsList.Items[i]).SendEvent; Inc(i); end; end; Объект-клиент создает в себе объект-синапс, назначает его событию OnEvent свой внутренний обработчик и регистрирует этот синапс на объекте-сервере. Вуаля! И получает оттуда уведомления. Кстати, в деструктор синапса можно встроить вызов события OnDestroy, и тогда объект-сервер, при регистрации клиента, может назначить ему обработчик и автоматически разрегистрировать его при уничтожении. Но это уже навороты.




Начало  Назад  Вперед



Книжный магазин