Глава 4.1 Окна, основы : Строение окна
February 23rd, 2009 Begemot Posted in Учебники
Первая часть четвертой главы книги Cross-Platform GUI Programming with wxWidgets в переводе на русский, на этот раз благодарим Лизунова Андрея за перевод.
Глава 4. Окна, основы
В этой главе, до того как описывать наиболее общие классы окон, используемых в приложении, мы познакомимся с основными элементами.. Эти элементы, почти наверняка, знакомы Вам из предыдущего опыта программирования или из приложений которыми вы пользовались. Несмотря на различия между системами, доступные элементы управления удивительно похожи по функциональности, wxWidgets управляет той частью, которая является общей. Оставшаяся часть обычно управляется, используя опциональные, платформо-зависимые, стили.
Строение окна
Естественно, вы знаете что представляет из себя окно, но для полного понимания как пользоваться wxWidgets АPI (Application Programming Interface — интерфейс программирования приложений) следует иметь ясное представление модели окна, которая используется в wxWidgets. Эта модель несколько отличается в зависимости от платформы. На рисунке 4.1 изображены основные элементы окна.
Рисунок 4.1 Элементы окна
Концепция окна
Окно это прямоугольная область с общим набором свойств: его размеры можно изменять, оно может нарисовать себя, его можно показать или спрятать и т.д.. Оно может содержать в себе другие окна (такие как фрейм с полосой меню — menu bar, панель инструментов – toolbar, панель состояния — status bar) или не дочерние окна (такие как статичный текст — static text control). Обычно, окно, которое вы видите на экране в приложении wxWidgets владеет соответствующим объектом класса wxWindow или производным от него, но это не всегда так. Например, раскрывающийся список (drop down list) в местном1 wxComboBox обычно не моделируется отдельным wxWindow.
Клиентская и не клиентская область
Когда мы ссылаемся на размер окна, мы обычно включаем туда и внешние измерения, декорации, такие как рамка и заголовок. Когда же мы ссылаемся на размер клиентской области окна, мы подразумеваем область внутри окна на которую или в которую могут быть помещены дочерние окна. Клиентская область не включает пространство которое занято полосой меню, панелью состояния и панелью инструментов.
Полосы прокрутки
Большинство окон способны изображать полосы прокрутки, управляемые этим же окном , а не добавленные приложением явно. Клиентская область, в таком слуаче, уменьшается на пространство используемое этой полосой прокрутки. Для оптимизации, только окнам со стилями wxHSCROLL и wxVSCROLL гарантируется владение их собственными полосами проктуки. Больше информации по скроллингу можно найти в этой главе дальше, где мы обсуждаем wxScrollWindow.
Каретка и курсор
Окно может иметь один экземпляр wxCaret (для отображения текущей позиции текста) и один экземпляр курсора (для отображения текущей позиции мышки). Когда мышка переходит в окно, wxWidgets автоматически отображает тот курсор, который был установлен для этого окна. Когда окошко получает фокусировку2 (focus), то каретка (если есть) будет показана на её текущей позиции, или на том месте, куда вы щелкнули кнопкой мышки при передаче фокусировки этому окну.
Верхнеуровневые окна
Окна резко делятся на верхнеуровневые окна (wxFrame, wxDialog, wxPopup) и на другие окна. Только верхнеуровневые окна могут быть созданы от NULL родителя и только верхнеуровневые окна имеют отложенное разрушение (они не удаляются до тех пор пока все остальные события (events) не будут обработаны). Исключая всплывающие (pop-up) окна, верхнеуровневые окна могут иметь декорации вроде заголовков (title bars) и закрывающих кнопок. Обычно их можно таскать по экрану и менять их размеры, если приложение позволяет.
Система координат
Система координат всегда начинается с (0,0) от верхнего-левого угла, окно измеряется в пикселях. Источник и масштаб могут варьироваться в зависимости от контекста устройства (device context) который используется для отрисовки окна. За дальнейшей информацией по контекстам устройств см. главу 5, «Начертание и печать»
Рисование
Когда окну требуется быть нарисованным оно получает два события: wxEVT_ERASE_BACKGROUND для отрисовки фона и wxEVT_PAINT для для отрисовки переднего плана. Готовый к использованию классы, типа wxButton, рисуют сами себя, но для того чтобы создать свой особый класс окна Вам понадобиться управлять этими событиями. Вы можете оптимизировать отрисовку, получая область обновления (ту часть, которую надо обновить) от окна.
Цвет и шрифт
Каждое окно имеет настройки цвета фона и переднего плана которые могут быть использованы чтобы определить цвет фона и (обычно реже) цвет переднего плана. Обработчик очистки фона по умолчанию использует цвет фона окна или, если он не был установлен, то соответствующий цвет или текстуру текущей цветовой схемы или темы. Окно также имеет настройки шрифта, которые могут использоваться или нет в зависимости от типа окна.
Окно Variant
В MAC OS X окно имеет концепцию «вариант окна» (window variant), таким образом оно может быть показано в зависимости от размеров: wxWINDOW_VARIANT_NORMAL (по умолчанию), wxWINDOW_ VARIANT_SMALL, wxWINDOW_VARIANT_MINI, or wxWINDOW_VARIANT_LARGE. Изменение к меньшему варианту полезны, когда у вас много информации для отображения а пространство ограниченно, но этим следует пользоваться умеренно. Некоторые приложения используют малый вариант повсеместно.
Изменение размеров
Когда изменяются размеры окна, приложением или пользователем, оно получает событие wxEVT_SIZE. Если у окна есть дети, они так же должны быть соответственно позиционированы и изменены в размерах, рекомендуется использовать калибровщики (sizers), они обсуждаются в главе 7, «Расположение окна используя калибровщики». Большая часть из набора окон имеет представление о размере и позиции по умолчанию если Вы передадите им wxDefaultSize или wxDefaultPosition (или -1 как персональный размер или значение позиции). С этой целью, каждый элемент управления реализует DoGetBestSize, который возвращает разумный размер по умолчанию основанный на содержимом элемента управления, текущем шрифте и других факторах.
Ввод
Любое окно может получить входящий сигнал от мышки в любое время, если только, какое нибудь другое окно не захватило мышку на время или если окно неисправно или намеренно отключено. Только окошко с фокусировкой может получать ввод с клавиатуры. Приложение может установить фокусировку окна самостоятельно, wxWidgets так же устанавливает фокусировку на окно когда пользователь щелкает на нём кнопкой мыши. Окну, которое получает фокусировку, посылается сообщение wxEVT_SET_FOCUS. Сообщение wxEVT_KILL_FOCUS посылается когда фокусировка передается другому окну. За более детальной информацией по управлению вводом, см. главу 6, «Управление вводом».
Обработка времени простоя и обновление интерфейса пользователя
Все окна являются (если только не указанно иное) получателями событий простоя (idle events: wxEVT_IDLE) которые посылаются когда все другие события были обработаны, заданные при помощи EVT_IDLE(func) макрос. За дальнейшей информацией см. «Обработка времени простоя» в главе 17, «Написание много поточных приложений»
Обновление интерфейса пользователя это особый вид обработки времени простоя, в которому все окна могут задать функцию которая обновляет состояние окна. Эта функция вызывается периодически во время простоя. В дальнейшем описании событий EVT_UPDATE_UI(id, func) обычно опускается для краткости. Обновление пользовательского интерфейса описано в главе 9, «Создание особых диалогов»
Создание и удаление окна
Вообще, окна создаются в куче при помощи оператора new, см. главу 15, «Управление памятью, отладка и контроль за ошибками» за деталями и исключениями. Большинство оконных классов позволяют создание в один или два шага. wxButton имеет типичную сигнатуру конструктора.
wxButton();
wxButton(wxWindow* parent,
wxWindowID id,
const wxString& label = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxT(“button”));
Следующий пример создания в один шаг использует значения по умолчанию из конструктора.
wxButton* button = new wxButton(parent, wxID_OK);
Вы обязаны передать не NULL родительское окно в конструктор если только это не фрейм(окно с рамкой) или не диалог. Это автоматически добавит дочернее окно в родителя и, когда родитель разрушается, дети будут также разрушены. Как мы видели ранее, Вы передаёте стандартный или определённый пользователем идентификатор в окно для того чтобы однозначно идентифицировать его. Вы можете также передать wxID_ANY, и wxWidgets сгенерирует подходящий идентификатор (отрицательное значение, чтобы отличить его от определённых пользователем или стандартных идентификаторов). Вы можете передать позицию и размер окна, валидатор, если есть подходящий (см. главу 9), стиль (см. следующий абзац) и строку с именем. Вы можете передать произвольную строку в качестве имени или проигнорировать её, это используется редко но было добавлено чтобы позволить подгонку окон в Xt и Motiff, которые требуют идентификации элемента управления по имени.
Для создания в два шага Вы используете конструктор по умолчанию и затем вызываете Create, которая имеет такую же сигнатуру как и полноценный конструктор. Пример создания в два шага:
wxButton* button = new wxButton;
button->Create(parent, wxID_OK);
Только когда вы вызываете Create создается подразумеваемое окно и событие wxEVT_CREATE посылается в окно если, требуется дальнейшая обработка, на этой стадии.
Зачем бы вам использовать создание в два шага? Одна причина в том что вы можете захотеть отложить полное создание окна до тех пор, пока оно действительно не понадобиться. Другая в том чтобы установить некие свойства окна перед вызовом Create, особенно это касается тех свойств, которые используются внутри вызова Create. Например, вы хотите установить дополнительный стиль wxWS_EX_VALIDATE_RECURSIVELY (который должен быть установлен посредством SetExtraStyle). При создании диалога, этот стиль используется внутри функции Create для первичного контроль (initial validation), таким образом, если Вам это требуется, то важно установить этот дополнительный стиль до создания диалога.
Когда вы создаёте wxWindow, или не верхне-уровневый унаследованный оконный класс, он всегда в состоянии «виден», так что если родитель виден в момент создания то ваше окно тоже будет видно. Затем, вы сможете использовать Show(false) чтобы спрятать окно, если потребуется. Это отличие от wxDialog и wxFrame, которые изначально создаются в состоянии «спрятанно» чтобы дать возможно приложению расположить элементы управления без мельканий, перед тем как показывать посредством Show или ShowModal (для модальных диалогов).
Окна уничтожаются посредством вызова Destroy (для верхне-уровневых окон) или delete (для дочерних окон), сообщение wxEVT_DESTROY посылается прямо перед тем как разрушается реальное окно. На самом деле, дочерние удаляются автоматически, таким образом он редко удаляются явно.
Стили окна
Окно имеет стиль и дополнительный стиль. Стили окна это лаконичный путь указать альтернативное поведение и внешний вид для окон в момент создания. Символы определены таким образом что-бы их можно было комбинировать в набор битов, используя побитовый оператор С++ «или». Например:
wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxTHICK_FRAME
Класс wxWindow имеет базовый набор стилей, таких как стиль с рамкой. Каждый последующий, в иерархии наследования, класс может добавлять стили. Дополнительный стиль (“extra” style) размещает значения которые нельзя подогнать в значение стиля3.
Сноски:
1 Родном, для данной ОС
2 Т.е. окно начинает принимать ввод, например, от клавиатуры.
3 Очевидно, здесь, автор имеет ввиду битовые наборы.
February 25th, 2009 at 5:24 pm
“Когда изменяются размеры окна, приложением или пользователем, оно получает событие wxEVT_SIZE. Если у окна есть дети, они так же должны быть соответственно позиционированы и изменены в размерах…”
Ой мамочки, окна с детьми – это оригинально
February 25th, 2009 at 10:50 pm
Это еще немного черновой вариант, он будет вычитан перед релизом:)
February 27th, 2009 at 11:21 am
Ну правильно. Куда ж я денусь 🙂
February 27th, 2009 at 9:12 pm
А чего обязательно ты, я вон сегодня уволился, теперь времени больше будет 🙂 хотя тут дома такой завал…
March 5th, 2009 at 8:14 pm
Люди есть вопрос юзаю С::В и MinGW хочу собрать окошко с wxFlatNotebook но немогу собрать. в билде нет майкфайла для MinGW где его достать или как его собрать
March 25th, 2009 at 10:14 am
[…] Продолжаю, вернее заканчиваю выкладывать перевод начала 4 главы сделанный Андреем Лизуновым. Начало про основы работы с окнами в wxWidgets здесь. […]