Главная » Delphi » Анатомия системы сообщений: библиотека VCL

0

Система  обмена  сообщениями не ограничивается библиотекой VCL, которая об рабатывает сообщения с помощью директивы message. После  того  как Windows  от правит сообщение, оно пройдет несколько последовательных этапов обработки, прежде чем  достигнет процедуры обработки сообщений создаваемого приложения. (Кроме того, оно может пройти еще несколько этапов обработки и после выполнениятакой  процедуры.) В принципе, сообщение остается доступным  на протяжении всего этого долгого пути.

Любое  сообщение Windows,  посланное без требования получения результатов обра ботки, первоначально обрабатывается методом Application.ProcessMessage(), в котором реализован главный цикл обработки сообщений средствами библиотеки VCL. Следующий  этап состоит в передаче сообщения обработчику события Applica- tion.OnMessage. Событие OnMessage генерируется при  выборке сообщения из оче реди приложения в методе ProcessMessage(). Поскольку сообщения, посылаемые без требования получения результатов обработки, не помещаются в очередь, событие On- Message для них не генерируется.

Для обработки сообщений, посылаемых с требованием предоставления результатов их

обработки, неявно вызывается функция API Win32 DispatchMessage(), которая, в свою очередь, передает каждое  сообщение функции StdWndProc(). Для отправляемых сооб щений эта функция вызывается непосредственно системой Win32. Функция  StdWnd- Proc() представляет собой написанную на ассемблере функцию низкого уровня,  которая принимает сообщение от Windows и переправляет его назначенному объекту.

Метод объекта, который получает сообщение, называется MainWndProc(). Начиная с этого  момента в программе можно  выполнять любую специальную обработку сообще ния, какая только  может потребоваться. Обычно в обработку сообщения на данном  эта пе вмешиваются только  для того,  чтобы  не допустить  стандартной обработки сообще ния средствами библиотеки VCL.

По   завершении  работы  метода   MainWndProc() сообщение  передается  методу WndProc() объекта, а затем поступает в распоряжение механизма диспетчеризации со общений. Этот  механизм, функционирующий в рамках  метода  Dispatch(), переправ ляет  сообщение дальше,  некоторой конкретной процедуре обработки сообщений, оп ределенной программистом или уже имеющейся в составе средств библиотеки VCL.

Наконец, сообщение достигает определенной в программе специализированной процедуры обработки сообщений данного типа. После  выполнения всех действий, пре дусмотренных пользовательской процедурой обработки и всеми унаследованными про цедурами,  которые вызываются с помощью ключевого слова  inherited, сообщение передается методу DefaultHandler(). Этот метод  осуществляет любые  завершающие действия по обработке сообщения и передает его функции API Win32 DefWindow- Proc() (или  другой стандартной процедуре обработки, например DefMDIProc()) для стандартной обработки средствами Windows.  Общая  схема механизма обработки сооб щений средствами библиотеки VCL представлена на рис. 3.2.

НА ЗАМЕТКУ

При обработке сообщений всегда следует вызывать унаследованный метод, за исклю- чением тех случаев, когда есть абсолютная уверенность в том, что стандартная обра- ботка сообщения не требуется.

CОВЕТ

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

Рис. 3.2. Схема механизма обработки сообщений средствами библиотеки VCL

Чтобы лучше понять схему обработки сообщений средствами библиотеки VCL, рас смотрим небольшую  программу, в которой обработка сообщений выполняется с помо щью методов Application.OnMessage и WndProc(), на стадии  процедуры стандарт ной обработки сообщений (DefaultHandler()). Проект называется CatchIt. Общий вид его главной формы показан на рис. 3.3.

end.CОВЕТ

Обычно для передачи сообщения унаследованному обработчику достаточно ключевого слова inherited, но в обработчиках, использующихся в процедурах WndProc() и De- faultHandler(), эта методика не работает. Поэтому приходится явно указывать имя унаследованной процедуры или функции, в данном случае inherited WndProc(Msg);

Обратите внимание: процедура DefaultHandler() несколько отличается от дру гих — она принимает один нетипизированный var параметр. Все дело в том, что первое слово  в значении параметра процедуры DefaultHandler() будет идентификатором сообщения, остальная часть  сообщения процедурой игнорируется. Поэтому  из сооб щения  можно  легко  извлечь его идентификатор с помощью явного приведения пара метра к типу TMessage.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии