Иллюстрированный самоучитель по Tirbo Pascal

       

Фаза событий


Обычно активные события (evKeyDown и evCommand) получают и обрабатывают видимые элементы, принадлежащие цепочке активности. Однако часто возникают ситуации, когда необходимо, чтобы активное событие обработал неактивный элемент. Например, если на экране активно окно скроллера с полосами скроллинга, то события от клавиатуры будут передаваться окну. Как заставить в этом случае полосы реагировать на нажатие клавиш PgUp или PgDn? Для этого в Turbo Vision предусмотрен специальный механизм, основанный на так называемой фазе события. Когда модальный элемент получает событие, его передача выполняется в следующей последовательности:

  • событие посылается в Z-порядке всем видимым элементам, которые принадлежат модальному элементу и у которых поле Options имеет установленный флаг ofPreProcess;
  • если событие не очищено ни одним из них, оно посылается активным элементам (по цепочке активности);
  • если событие все еще не очищено, оно посылается в Z-порядке всем видимым элементам, у которых установлен флаг ofPostProcess.
  • Таким образом, Вы должны установить флаги 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).


    Содержание раздела