Фаза событий
Обычно активные события (evKeyDown и evCommand) получают и обрабатывают видимые элементы, принадлежащие цепочке активности. Однако часто возникают ситуации, когда необходимо, чтобы активное событие обработал неактивный элемент. Например, если на экране активно окно скроллера с полосами скроллинга, то события от клавиатуры будут передаваться окну. Как заставить в этом случае полосы реагировать на нажатие клавиш PgUp или PgDn? Для этого в Turbo Vision предусмотрен специальный механизм, основанный на так называемой фазе события. Когда модальный элемент получает событие, его передача выполняется в следующей последовательности:
Таким образом, Вы должны установить флаги ofPreProcess или ofPostProcess (или оба вместе) при инициации видимого элемента, если хотите, чтобы он мог получить активное событие до или после (или и до и после) того, как его получат активные элементы.
Для предыдущего примера необходимо инициировать полосы скроллинга с установленными флагами ofPostProcess, если требуется, чтобы полосы «увидели» и обработали нажатие на клавиши смещения курсора, PgUp, PgDn и т.д. Разумеется, в этом случае полосы получат событие evKeyDown только при условии, что скроллер сам не обработает это событие.
В некоторых ситуациях элемент, перехватывающий событие и до, и после активных элементов, должен модифицировать свое поведение в зависимости от фазы события. Рассмотрим такой типичный пример. Пусть в программе создано диалоговое окно, имеющее строку ввода и три кнопки, для которых определены командные клавиши Q, W, Е. Как добиться того, чтобы эти клавиши использовались в качестве командных клавиш, т.е. приводили к «нажатию» соответствующих кнопок при условии, что активна любая кнопка, а в сочетании с клавишей Аlt - если активна строка ввода (именно так используются командные клавиши в диалоговом окне среды Турбо Паскаля)? Если инициировать кнопки с флагом ofPreProcess, они смогут без труда определить факт нажатия на командную клавишу, однако в строке ввода пользователь не сможет ввести буквы Q, W и E, так как они будут перехвачены кнопками до того, как событие от клавиши получит строка ввода. Если инициировать кнопки с флагом ofPostProcess, пользователь не сможет использовать сочетания Аlt-<клавиша> для нажатия кнопки, если активна строка ввода: все события evKeyDown будут в этом случае направляться в строку. Решение очевидно: нужно определить оба флага, но на препроцессорной фазе следует проверять ввод Аlt-<клавиша>, а на постпроцессорной - <клавиша>.
Для реализации этих проверок обработчик событий объекта TButton должен каким-то образом определить текущую фазу события. С этой целью в любой группе предусмотрено поле Phase. Это поле доступно только для чтения и содержит одно из значений phPreProcess, phFocused или phPostProcess в зависимости от фазы события.
Следующий фрагмент иллюстрирует ту часть обработчика событий кнопок, которая проверяет командную клавишу:
evKeyDown: {Это часть оператора саsе}
begin
С := HotKey(Title*); {Получаем в С букву клавиши}
{Проверяем Alt-<клавиша>:}
if (Event.KeyCode = GetAltCode(С)) or
{Проверяем <клавиша>:}
(Owner*.Phase = phPostProcess) and (C <> #0)
and (UpCase(Event.CharCode) = C) or
{Проверяем активность и нажатие пробела:}
(State and sfFocused <> 0) and (Event.CharCode = ' ') then
Press {Да, кнопка выбрана: выдаем нужную команду}
end;
В этом фрагменте не показанная здесь функция HotKey выделяет из надписи на кнопке символ командной клавиши (он обрамляется символом «~»), а стандартная для Turbo Vision функция GetAltCode преобразует этот символ в расширенный код клавиш Аlt-<клавиша>. Метод TButton.Press реализует «нажатие» на кнопку и выдает сообщение evBroadcast с командой TButton. Command.
Отметим, что рассмотренный пример приведен только в качестве иллюстрации: стандартный объект TButton реализует свой обработчик событий именно таким образом и Вам нет нужды переопределять его (по умолчанию экземпляр TButton инициируется с установленными флагами ofPreProcess и ofPostProcess).