Метод DefaultHandler виртуальный, в классе TObject он не выполняет никаких действий, но наследники его переопределяют. Впервые он переопределяется в классе TControl для обработки сообщений, связанных с получением и установкой заголовка окна — WM_GETTEXT, WM_GETTEXTLENGTH и WM_SETTEXT. Напомним, что класс TControl является предком для всех визуальных компонентов, а не только оконных, и появление обработчика системных сообщений в этом классе — часть той имитации обработки сообщений неоконными компонентами, о которой мы уже говорили.
В классе TWinControl метод DefaultHandler также переопределен. Помимо передачи некоторых сообщений дочерним окнам (об этом мы будем подробнее говорить чуть позже) и обработки некоторых внутренних сообщений он вызывает оконную процедуру, адрес которой хранится в свойстве DefWndProc. Это свойство содержит адрес, который был присвоен полю WindowClass.lpfnWndProc структуры TCreateParams в методе CreateParams. По умолчанию это поле содержит адрес стандартной оконной процедуры DefWindowProc. Как было сказано ранее, обработка сообщений при использовании API обычно завершается вызовом этой процедуры. В классе TCustomForm метод DefaultHandler также переопределен, если форма является MDI-формой, сообщения, присланные ей, передаются в процедуру DefFrameProc (за исключением WM_SIZE, которое передается в DefWindowProc) независимо от того, какое значение имеет свойство DefWindowProc. Для всех остальных типов форм вызывается унаследованный от TWinControl DefaultHandler.
Повторим еще раз всю цепочку обработки сообщений оконными компонентами VCL (рис. 1.7). Для каждого компонента создается уникальная оконная процедура, которая передает управление методу MainWndProc. MainWndProc передает управление методу, указатель на который хранится в свойстве WindowProc. По умолчанию это метод компонента WndProc. Он осуществляет обработку некоторых сообщений, но в большинстве случаев передает управление методу Dispatch, который ищет среди методов компонента или его предков обработчик данного сообщения. Если обработчик не найден, управление получает метод DefaultHandler (он может также получить управление и в том случае, если обработчик найден, но он вызывает inherited). DefaultHandler самостоятельно обрабатывает некоторые сообщения, но большинство из них передаётся оконной процедуре, адрес хранится в свойстве DefWndProc (по умолчанию это стандартная функция Windows API DefWindowProc).
Рис. 1.7. Блок-схема оконной процедуры оконных компонентов VCL
Класс TControl имеет метод Perform, с помощи которого можно заставить визуальный компонент выполнить обработку конкретного сообщения в обход оконной процедуры и системного механизма передачи сообщений. Perform приводит к непосредственному вызову метода, указатель на который хранится в свойстве WindowProc. Дальше цепочка обработки сообщений такая же, как и при получении сообщения через оконную процедуру. Для оконных компонентов вызов Perform по своим последствиям практически эквивалентен передаче сообщения с помощью SendMessage с двумя исключениями. Во-первых, при использовании SendMessage система обеспечивает переключение между нитями, и сообщение будет выполнено в той нити, которая создала окно, a Perform никакого переключения не производит, и обработка сообщения будет выполнена той нитью, которая вызвала Perform. Поэтому Perform, в отличие от SendMessage, можно использовать только в главной нити (напомним, что VCL — принципиально однонитевая библиотека, и создание форм вне главной нити с ее помощью недопустимо). Во-вторых, Perform выполняется чуть быстрее, т.к. оконная процедура и метод MainWndProc исключаются из цепочки обработки сообщения.
Но основное преимущество Perform перед SendMessage заключается в том, что Perform пригоден для работы со всеми визуальными компонентами, а не только с оконными. Неоконные визуальные компоненты не могут иметь оконной процедуры, но цепочка обработки сообщений у них есть. В ней отсутствует оконная процедура и метол MainWndProc, a DefaultHandler не вызывает никаких стандартных оконных процедур, но во всем остальном эта цепочка полностью эквивалентна цепочке оконных компонентов. Таким образом, цепочка обработки сообщений оконных компонентов имеет две точки входа: оконную процедуру и метод Perform, а цепочка неоконных компонентов — только метод Perform. Следовательно, метод Perform универсален: он одинаково хорошо подходит как для оконных, так и для неоконных компонентов. Он широко применяется в VCL, т.к. позволяет единообразно работать с любыми визуальными компонентами.