Обработка событий в wxWidgets.

November 8th, 2011 Begemot Posted in Учебники

Процесс перевод книги продолжается.

Дополнение H: Обработка событий в wxWidgets.

Сейчас мы попробуем подробно осветить вопрос обработки событий в wxWidgets , включая все детали, опушенные когда мы об этом говорили в прошлый раз.
Когда приходит событие от оконной системы, wxWidgets вызывает функцию wxEvtHandler::ProcessEvent принадлежащую первому объекту окна с генерировавшего событие.
  
Рисунок H-1 демонстрирует порядок поиска в таблице, так как его выполняет ProcessEvent. Все это работает следующим образом:

1. Если объект находится в заблокированном состоянии (после вызова wxEvtHandler::SetEvtHandlerEnabled), функция сразу переходит к шагу №6. 

2. Если объект является окном (наследник класса wxWindow) ProcessEvent рекурсивно вызывает все валидаторы установленные для этого окна. В случае успеха, функция завершается.    

3. Иначе вызывается SearchEventTable для обработчика данного события. Если поиск не увенчался успехом, то поиск продолжается в таблице для базового класса, далее следующего базового класса, и так далее по все иерархии до тех пор пока соответствующий обработчик не будет найден или не закончится иерархия, в первом случае функция прекращает работу.

4. Поиск проходит вниз по всей цепочке обработчиков событий (обычно в ней всего один элемент). Функция завершается в случае, если найден подходящий обработчик.

5. Если объект наследник wxWidnow и событие должно быть распространено (обычно распространяются только события типа wxCommandEvent), ProcessEvent рекурсивно вызывает обработчики родительских окон. В случае возврата true, функция прекращает работу.

6. И наконец, вызывается ProcessEvent объекта приложения.
 
Рисунок H-1. Поток обработки события

h-1

 

Обратите особое внимание на пятый шаг. Люди часто приходят в замешательство от этой мощной и гибкой возможности системы обработки событий в wxWidgets или просто игнорируют ее. Говоря другими словами, события с установленным флагом, разрешающим распространение (обычно это достигается путем прямого или косвенного наследования от wxCommandEvent) путешествуют вверх по иерархии окон, от дочернего к родительскому окну, до тех пор пока не будет достигнут максимальный уровень распространения или не найдется подходящий обработчик, который НЕ вызовет Skip().   
 

Когда командное событие распространяться в верх к родительскому окну, распространение прекращается по достижению родительского диалога, если он есть. Это гарантирует что вы не рискуете получить неожиданное событие от контролов вашего диалога (которые скорее всего будут оставлены диалогом не обработанными по сколько он ничего не знает о них) выше написанное справедливо для модального диалога. Однако, события свободно распространяются между фреймами. Причиной для такого выбора послужило то, что обычно приложение имеет всего несколько фреймов, и связи ребенок – родитель вполне осознаются программистом. В то время как в сложной программе, может быть весьма сложно или даже невозможно, отследить все используемые диалоги (помните что некоторые их них вполне могут создаваться самой библиотекой). Если вам по каким-либо причинам необходимо иное поведение, вы можете явно вызвать SetExtraStyle(wxWS_EX_ BLOCK_EVENTS), чтобы предотвратить распространение событий за пределы данного окна, или вы можете сбросить этот флаг для диалогов, где он установлен по умолчанию.

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

Учтите, что вы вполне можете заместить стандартную функцию ProcessEvent для перенаправленния обработки сообщений. Это, к примеру, сделано для в части библиотеки отвечающей за реализацию архитектуры документ-представление, для того что бы позволить размещение обработчиков событий как в классе документа, так и в классе представления. Для определения, является ли событие командой (скорее всего вы хотите перенаправлять только командные события) в целях эффективности вы можете использовать wxEvent::IsCommandEvent вместо, использования достаточно медленной системы типов времени выполнения.    

Related:

Posted in Учебники | Tags:

4 Responses to “Обработка событий в wxWidgets.”

  1. а как дела с переводом главы 4 ?

  2. Пока к сожалению печально:(

  3. Я бы хотел поучаствовать в переводе, подробности по мылу.

  4. Хорошая идея 🙂
    Я Алексею написал, он руководит, завтра появистя – может что
    ответит