Форма и виджеты


В этой статье содержиться детальное описание формы, различных типов виджетов и их состояний, и объясняются детали взаимодействия между формой и виджетами. После прочтения ее Вы узнаете все необходимые детали о внутреннем поведении ядра фреймверка касающееся форм и виджетов, и будете лучше понимать его архитектуру и преимущества.



О форме

Как Вы уже знаете, форма является контейнером для всех виджетов. Вы можете поместить виджеты на форму или на другие виджеты на форме и таким образом создать хороший графический интерфейс для Вашего приложения. Форма описывается интерфейсом IForm и реализована в классе CForm. Форма получает сообщения от пользователя и операционной системы(через присоединенное окно) и управляет ими действуя как проводник и распределитель. Она отвечает за расшифровку базовых событий и преобразование их в сообщения виджетам, которые смогут их понять. Она так же отвечает за отправку событий правильным виджетам. Например, когда Вы кликаете по форме, она ищет виджет, находящийся под курсором мышы, и, если таковой найден, отправляет сообщение именно этому виджету.

Форма так же содежит и управляет некоторыми полезными объектами, которые могут использоваться виджетами на форме. Вот эти объекты:

  • Рендер(renderer) отвечает за все операции рисования. Все виджеты используют его для собственной отрисовки на форме. Виджет может получить доступ к нему с помощью метода формы getRenderer(). Рендер описывается интерфейсом IRenderer.
  • Всплывающая подскзка(hint) ответственна за показ подсказок, когда указатель мыши оказывается над виджетом. Текущий менеджер подсказок можно получить методом getHint(), а установить новый можно методом setHint(). Обычно виджеты не пользуются этим объектом. Форма же наоборот интенсивно использует подсказки. Возможность изменения менеджера подсказок можно использовать для создания виджетов с уникальным типом всплывающих подсказок. Они могут устанавливать свой собственный менеджер подсказок, когда добавляются на форму, и восстанавливать старый, когда удаляются с формы. Менеджер подсказок описывается интерфейсом IHint.
  • Стиль(style) отвечает за изменение внешнего вида всех или некоторых виджетов размещенных на форме. По умолчанию у формы нет стиля, так что все виджеты рисуются в том виде, в котором они были созданы. Доступ к текущему используемому стилю можно получить с помощью метода getStyle(), а новый стиль можно установить с помощью метода setStyle(). При изменении стиля формы все ее виджеты, у который свойство UseParentStyle равно true, получают уведомление NotifyOnParentStyleChange() через сервис. Стиль описывается интерфейсом IStyle.
  • Свойство шрифт формы содержит объект для управления свойствами шрифта формы. Текущий активный шрифт можно получить методом getFont(), а установить новый можно методом setFont(). Если у виджета нет собственного шрифта, он использует шрифт формы. При изменении шрифта формы все виджеты на ней, у которых свойство UseParentFont равняется true, получают уведомление об изменении через метод NotifyOnParentFontChange() своего сервиса. Шрифт описывается интерфейсом IFont.
  • Объект формы каретка(caret) отвечает за рисование каретки в различных виджетах, которые поддерживают ввод данных с клавиатуры. Текущий менеджер каретки можно получить методом getCaret(), а установить новый методом setCaret(). Менеджер каретки описывается интерфейсом ICaret.
  • Трансформация(transform) отвечает за положение формы на экране. Получить к ней доступ можно с помощью метода getTransform(). Объект трансформации формы(контролирующий ее положение) нельзя изменить.
  • Трансформация элементов управления(transform controls) отвечает за применение глобальной трансформации ко всем виджетам на форме. Для доступа к ней используется метод getTransformControls(), а для установки новой метод setTransformControls(). Такая трансформация может быть полезной, когда должна быть применена сразу ко всей форме. Это может быть масштабирование или прокрутка или даже что-то совсем экзотическое. Обе трансформации описываются одним и тем же интерфейсом ITransform.

Кроме объектов описанных выше, у формы есть множество свойств, которые изменяют ее внешний вид и контролируют определенным образом взаимодействие с виджетами. У формы так же есть множество событий, которые Вы можете использовать для получения уведомлений обо всех изменения на форме. Вы можете узнать больше о свойствах, события и методах формы на странице документации IForm с описанием интерфейса формы.

Типы виджетов

Есть 3 различных типа виджетов определенных во фреймверке. Мы опишем их здесь в порядке сложности.

Первый тип виджетов это компонент(component). Виджеты этого типа реализуют интерфейс IComponent и обычно наследуются от класса CComponent, содержащего реализацию по умолчанию. Виджеты этого типа не видимы на форме и их нельзя поместить на другие виджеты. Назначение этих виджетов - предоставить какую-то вспомогательную функциональность. Например, компонент может хранить список картинок или периодически запускать какое-то действие. Компоненты так же могут быть очень сложными и мощными. Например, это даже может быть целый web-сервер. Не смотря на то, что компоненты не отображаются на форме, иногда у них может быть визуальное представление. Например, компонент может показывать форму или диалоговый виджет для выбора цвета или файла на жестком диске.

Второй тип виджетов называется элемент управления(control). Это обычный, наиболее часто используемый, тип виджета. Его можно поместить как непосредственно на форму так и на другие виджеты, которые так же являются элементами управления(хорошо, есть конечно же некоторые виджеты, которые запрещают размещать на себе другие виджеты, и есть некоторые виджеты, которые разпрещают размещать себя на других виджетах или форме, или даже только определенных виджетах, но в целом идея верна). Эти виджеты имеют графическое представление на форме. Вот несколько примеров виджетов с типом элемент управления(control): метка(label), поле ввода текста(text input), панель(panel), календарь(month calendar), таблица(table), часы(clock). Элементы управления реализуют интерфейс IControl и обычно наследуются от класса CControl. Элементы управления наследуются от компонентов и имеют все их свойства и методы.

И, наконец, есть третий тип виджетов, которые впервые были добавлены в релизе 9.0.0. Это dialog box(диалоговые виджеты). Этот тип виджетов наследуется от control(элемента управления) и имеет все его свойства и методы. Различие между диалоговыми виджетами и элементами управления заключается в том, как с ними работает форма. Диалоговые виджеты рассматриваются как виджеты, которые содержат другие виджеты и работают как форма внутри формы. Это значит что, когда пользователь активирует любой виджет размещенный на диалоговом виджете, или кликает на самом диалоговом виджете, форма активирует этот диалоговый виджет. Когда пользователь закрывает диалоговый виджет, диалоговый виджет, который был активен раньше, становиться снова активным(если таковой был конечно же). Со стороны пользователя это выглядит как работа с различными дочерними формами внутри главной формы. Все диалоговые виджеты реализуют интерфейс IDialogBox и обычно наследуют класс CDialogBox. Когда диалоговый виджет активируется, он получает уведомление NotifyOnSetActive() через свой сервис и вызывается его событие OnSetActive. В то же время все остальные виджеты на форме получают уведомление NotifyOnDialogBoxActivate() через их сервисы и вызываются их уведомления OnDialogBoxActivate. Аналогично, при деактивации диалогового виджета, приходят уведомления NotifyOnKillActive(), NotifyOnDialogBoxDeactivate() и вызываются события OnKillActive и OnDialogBoxDeactivate у диалогового виджета и остальных виджетов соответственно.

Начиная с выпуска 9.0.0 Конструктор Форм может генерировать файл с кодом формы в виде диалогового виджета. Так что Вы можете создать форму как обычно и использовать ее по Вашему выбору и как обычную форму и как диалоговый виджет в Вашем приложении.

Состояния виджетов

Виджеты типа элемент управления и диалоговый виджет могут иметь различные состояния, которые воздействуют на их взаимодействие с формой.

Во-первых, виджет может быть видимым(visible) или невидимым(hidden). Когда он не видим, он не отображается на форме и пользователь не может взаимодействовать с ним. Все виджеты, которые находятся на невидимом виджете, так же считаются невидимыми. Состояние видимости абсолютно, что значит, что дочерние виджеты ничего не могут сделать для изменения поведения или сделать себя видимыми на форме, если один из родительских виджетов невидим. Состояние видимости контролируется методом setVisible() из IControl и его можно проверить методом isVisible(). Некоторые виджеты могут запрещать делать их невидимыми путем переопределения метода setVisible(). Такое изменение разрешено фреймверком и правильно обрабатывается его объектами. Когда виджет становиться невидимым путем изменения его состояния видимости(не путем изменения состоянния видимости родительских виджетов) его сервис получает уведомление NotifyOnHide() и вызывается его событие OnHide. Дополнительно непосредственный родитель виджета(другой виджет или форма) получает уведомление NotifyOnChildHide() через сервис и вызывается событие родителя OnChildHide. Аналогично существуют уведомления NotifyOnShow() и NotifyOnChildShow() и события OnShow и OnChildShow для информирования о том, что виджет становится видимым.

Виджет может быть доступным(enabled) или недоступным(disabled). Когда он недоступен, он все еще рисуется на форме(возможно в слегка отличающемся стиле), однако пользователь не может взаимодействовать с ним. Так же, когда виджет недоступен, он все еще получает уведомления и что делать с ними, игнорировать или обрабатывать, находится под полным контролем виджета. Важно не забывать об этом при создании Ваших собственных виджетов. Из-за предидущего замечания состояние не является абсолютным. Оно относительно и зависит от реализации виджета. Несмотря на это, некоторые состояния виджета, которые будут описаны немного позже, не могут быть применены к недоступному виджету. Вы можете проверить доступен ли виджет или нет его методом isEnabled(), а установить новое состояние методом setEnabled() из интерфейса IControl. Как и с состоянием видимости, некоторые виджеты могут переопределять метод setEnabled() для предотвращения изменения состояния. Когда виджет становиться недоступным при изменении его состояния(не при изменении соответствующего состояния родительских виджетов) его сервис получает уведомление NotifyOnDisable() и вызывается его событие OnDisable. Дополнительно непосредственный родитель виджета(другой виджет или форма) получает уведомление NotifyOnChildDisable() через сервис и вызывается его событие OnChildDisable. Аналогично, есть уведомления NotifyOnEnable() и NotifyOnChildEnable() и события OnEnable и OnChildEnable для информировании о том, что виджет становится доступным.

Следующее состояние это focused(в фокусе). Элемент управления находящийся в этом состоянии получает все сообщения с клавиатуры. Это состояние обычно применимо к виджетам, которые позволяют что-то делать с помощью клавиатуры(вводить текст или переключаться между строками или вкладками). Виджет должен информировать о том, может ли он быть в фокусе или нет с помощью метода isAcceptFocus(). Если Вы создаете свой виджет и наследуюте его от CControl(предпочитаемый и наиболее часто используемый вариант), Вам просто нужно передать соответствующий флаг в его конструктор. Недоступные(Disabled) виджеты не могут находиться в фокусе. Только один виджет на форме может быть в фокусе одновременно. Если фокус передается другому виджету, текущий виджет в фокусе теряет это состояние автоматически. Передать фокус виджету можно методом setFocusedControl() из IForm или методом setFocus() из IControl, который использует первый вариант. Так же форма автоматически передает фокус виджету когда пользователь кликает на нем(если он может получить фокус и доступен(enabled) конечно же) или переключается между виджетами с помощью комбинаций Tab или Shift+Tab(эту возможность тоже можно отключить установив свойству FocusByTab формы значение false). Последнее поведение так же зависит от свойств виджета TabStop и WantTabs. Если первое свойство равно false, виджет не будет получать фокус при переключении комбинациями клавиш, второе же свойство предотвращает потерю фокуса. Вы можете проверить в фокусе ли виджет используя его метод isFocused() или сравнивая его с виджетом, который возвращает метод getFocusedControl() формы. Не рекомендуется переопределять ни один из предидущих методов. Все что нужно это передать соответствующие флаги в конструктор CControl. Когда виджет получает фокус, его сервис получает уведомление NotifyOnSetFocus() и вызывается его событие OnSetFocus. В дополнение все виджеты на форме(кроме получившего фокус) получают уведомление NotifyOnControlSetFocus() через их сервисы и вызываются их события OnControlSetFocus. Аналогично существуют уведомления NotifyOnKillFocus() и NotifyOnControlKillFocus() и события OnKillFocus и OnControlKillFocus для информирования о том, что виджет теряет фокус.

Следующие два сосотояния специальные. Они очень похожи так что мы опишем их в одном параграфе. Эти состояния называются состояниями захвата(capture). Первое это состояние захвата клавиатуры(capture keyboard) и второе захвата мышы(capture mouse). Эти состояния позволяют виджетам получать уведомления от клавиатуры и мышы даже если они не в фокусе и не находятся под указателем мышы. Это что-то типа перехвата уведомлений. Только один виджет может захватить ввод с клавиатуры в один и тот же момент времени и аналогичто только один виджет может захватить ввод с мышы. Для начала захвата ввода с клавиатуры нужно использовать метод CaptureKeyboard() интерфейса формы IForm с указанием виджета, который получит захват клавиатуры. То же самое справедливо и для захвата ввода мышы только метод называется CaptureMouse(). Узнать какой элемент управления захватил ввод с клавиатуры или мышы можно с помощью методов формы getCaptureKeyboardControl() и getCaptureMouseControl() соответственно. Так же можно проверить захватил ли виджет ввод с клавиатуры или мышы используя его методы описанные в IControl и называющиеся isCaptureKeyboard() и isCaptureMouse(). Когда виджету больше не требуется захват ввода с клавиатуры или мышы, нужно вызвать методы формы ReleaseCaptureKeyboard() или ReleaseCaptureMouse(). В этом случае состояние захвата передается виджетам, которые захватывали ввод ранее(если таковые были). Начало и конец захвата ввода обычно управляется самим виджетом и полностью зависит от его реализации. Например, если Вы создаете виджет, который является редактором изображений, Вам скорее всего понадобиться захватывать ввод мышы при определенных условиях. В качестве примера такого условия может быть рисование линии. Обычно, когда указатель мышы покидает область виджета, виджет перестает получать уведомления о перемещении указателя. В случае, когда пользователь начинает рисовать линию(нажимает кнопку мышы в какой-то точке виджета) и перемещает указатель мышы, он может нечаянно(или намеренно) переместить указатель за границу виджета и линия перестанет обновляться, когда указатель движеться за пределами виджета. Более того, виджет не узнает когда пользователь отпустит кнопку мышы, чтобы завершить рисование линии. Такое поведение неверное. Правильного поведения можно добиться начав захват ввода мышы сразу как только пользователь нажимает кнопку мышы указывая начало линии. В этом случае события мышы будут отправлятся виджету даже если указатель мышы находится за пределами виджета. Когда виджет начинает захват ввода клавиатуры или мышы, его сервис получает уведомление NotifyOnSetCaptureKeyboard() или NotifyOnSetCaptureMouse() и вызывается его событие OnSetCaptureKeyboard или OnSetCaptureMouse. Дополнительно все виджеты на форме(за исключеием виджета, который только что захватил ввод) получают уведомление NotifyOnControlSetCaptureKeyboard() или NotifyOnControlSetCaptureMouse() через сервис и вызываются их события OnControlSetCaptureKeyboard или OnControlSetCaptureMouse. Аналогично есть уведомления NotifyOnKillCaptureKeyboard(), NotifyOnKillCaptureMouse(), NotifyOnControlKillCaptureKeyboard() и NotifyOnControlKillCaptureMouse(), а так же события OnKillCaptureKeyboard, OnKillCaptureMouse, OnControlKillCaptureKeyboard и OnControlKillCaptureMouse для информирования виджетов о потере состояний захвата.

Каждый виджет также может быть под указателем курсора мышы(hovered). Форма полностью контролирует это свойство и определяет какой виджет находится под указателем автоматически при необходимости. Узнать какой элемент управления сейчас находится под указателем мышы можно с помощью метода getHoveredControl() формы IForm. Так же можно проверить находится ли элемент управления под курсором мышы или нет методом isHovered() из IControl. Когда виджет попадает под курсор его сервис получает уведомление NotifyOnMouseHover() и вызывается его событие OnMouseHover. Аналогично есть уведомление NotifyOnMouseLeave() и событие OnMouseLeave для информирования виджета о том, что курсор мышы покидает его. Эти уведомления и события вызываются независимо от состояния захвата мышы. Если, по какой либо причине Вам нужно принудительно обновить это состояние, Вы можете вызвать метод UpdateHoveredControl() формы.

Следующее состояние active(активный). Это состояние представляет собой простой индикатор, который может быть получен виджетом и который будет потерян при любом действии(например при клике где-нибудь или при передаче фокуса следующему виджету). Это состояние может быть полезным для таких виджетов как выпадающие списки. Когда пользователь кликает на стрелку чтобы увидеть выпадающий список с опциями, список появляется и виджет говорит форме, что он хочет быть активным. Когда пользователь далее производит любые действия, форма удаляет активное состояние с виджета и посылает ему уведомление об этом и виджет прячет список с опциями. Для установки активного состояния используйте метод setActiveControl() из IForm. Для получения виджета имеющего активное состояние в данный момент можно воспользоваться методом формы getActiveControl(). Чтобы проверить является ли виджет активным виджетом, можно использоваь его метод isActive() описанный в IControl. Когда виджет становится активным его сервис получает уведомление NotifyOnActivate() и вызывается его событие OnActivate. Аналогично есть уведомление NotifyOnDeactivate() и событие OnDeactivate для информирования виджета о потере активного сосотояния.

Modal(модальное) состояние добавляет ограничения на сообщения, передаваемые виджетам. Если виджет находится в модальном состоянии, только этот виджет и его дочерние виджеты могут получать сообщения(уведомления) ввода. Только один виджет может быть модальным одновременно. При передаче модального состояния другому виджету, текущий модальный виджет теряет это состояние, однако остается в истории модальных виджетов формы и, когда новый модальный виджет освобождает модальное состояние, становиться модальным снова. Виджет может быть модальным только если его метод isAcceptModal() возвращает true. Не рекомендуется переопределять этот метод. Вместо этого используйте соответствующий аргумент конструктора CControl. Модальное состояние активно используется с диалоговыми виджетами. Сделав диалоговый виджет модальным, можно предотвратить автоматическое переключение на другой диалоговый виджет(если такой есть) или деактивирование кликом в каком-нибудь месте за пределами диалогового виджета. Чтобы сделать виджет модальным сущетвует метод setModalControl() в интерфейсе IForm. У формы так же есть метод getModalControl(), который возвращает текущий виджет в модальном состоянии. Так же можно проверить что виджет имеет модальное состояние методом isModal(), находящимся в IControl. Для освобождения модального состояния и передачи его предидущему диалоговому виджету(если таковой имеется), используйте метод формы ReleaseModal(). Для освобождения модального сосотояния и предотвращение его передачи любому виджету бывшему модальным до текущего, используйте метод формы setModalControl() с аргументом nullptr. Это позволяет освободить текущее модальное состояние текущего модального виджета и очистить историю модальности. Когда виджет становиться модальным его сервис получает уведомление NotifyOnSetModal() и так же вызывается его событие OnSetModal. Дополнительно, все виджеты на форме(кроме того, который получил модальное состояние) получают уведомление NotifyOnControlSetModal() через сервис и вызывается их событие OnControlSetModal. Аналогично есть уведомления NotifyOnKillModal() и NotifyOnControlKillModal() и события OnKillModal и OnControlKillModal для информирования об утрате модального состояния.

Виджеты, являющиеся диалоговыми, могут иметь свое собственное состояние активности(active), указывающее какой именно диалоговый виджет сейчас активен(не путать с обычным состоянием активности; это состояние активности только для диалоговых виджетов и оно работает по другому). Как было описано в предидущей главе, форма активирует и деактивирует диалоговые виджеты автоматически. Однако это так же можно сделать програмным путем используя метод setActiveDialogBox() из IForm для автивации другого диалогового виджета или деактивации всех и очистки истории передав парметр nullptr. Метод формы getActiveDialogBox() может помочь получить текущий активный диалоговый виджет. Так же можно проверить является ли диалоговый виджет активным его методом isActiveDialogBox() описанным в интерфейсе IDialogBox. Когда диалоговый виджет становиться активным его сервис получает уведомление NotifyOnSetActive() и вызывается его событие OnSetActive. В дополнение все виджеты на форме(кроме этого диалогового виджета) получают уведомление NotifyOnDialogBoxActivate() через сервисы и вызываются их события OnDialogBoxActivate. Аналогично есть уведомления NotifyOnKillActive() и NotifyOnDialogBoxDeactivate(), а так же события OnKillActive и OnDialogBoxDeactivate, для информирования о том, что диалоговый виджет теряет состояние активности.

И, наконец, есть так называемое состояние input(ввод). В этом состоянии виджет получает все необработанные события от клавиатуры и мышы. Это может быть полезным для виджетов, которые модифицируют области границ и заголовка окна. Для установки input-виджета используйте метод setInputControl() интерфейса формы IForm. Метод getInputControl() формы возвращает текущий input-виджет. Только один виджет может быть назначен input-виджетом на форме.

Не все комбинации состояний, описанных выше, могут использоваться вместе. Ниже Вы найдете список ограничений применяющийся к комбинациям состояний. Если один из критериев не применим, виджет теряет соответствующий статус. Если состояние отсутствует в списке ниже, это значит что на него нет никаких ограничений.

  • Focused(В фокусе): должен быть visible(видимым), enabled(доступным) и быть на modal(модальном) виджете, если таковой существует.
  • Capture keyboard(Захват клавиатуры): должен быть visible(видимым), enabled(доступным) и быть на modal(модальном) виджете, если таковой существует.
  • Capture mouse(Захват мышы): должен быть visible(видимым), enabled(доступным) и быть на modal(модальном) виджете, если таковой существует.
  • Hovered(под указателем мышы): доложен быть visible(видимым).
  • Active(Активный виджет): должен быть visible(видимым), enabled(доступным) и быть на modal(модальном) виджете, если таковой существует.
  • Modal(модальный): должен быть visible(видимым).
  • Active dialog box(Активное диалоговое окно): должно быть visible(видимым) и быть на modal(модальном) виджете, если таковой существует.

Также, все состояния из списка выше будут утрачены для виджета, если он удаляется с формы.

Диалоговые виджеты

Начиная с выпуска 9.0.0 Конструктор Форм может генерировать заголовочный файл прототипа формы в виде диалогового виджета. Это означает, что вместо стандартной формы можно получить диалоговый виджет. Вам нужно создать класс для Вашего диалогового виджета, наследующий класс экспортированный в заголовочный файл и реализовать его методы уведомлений, абсолютно так же как Вы делалаете для форм. Реализация проактически идентична реализации обычных форм. Различие получается только в конструкторе, который больше похож на конструктор CControl, чем конструктор формы. Позже Вы можете создать свой диалоговый виджет таким же способом, как Вы создаете другие виджеты(просто создаете его и размещаете на форме или виджете: m_pMyDlg = new CDialogBoxMyDlg(form)); // В этом случае Вы добавили конструктор, который создает диалоговый виджет и помещает его на форму вызывая метод setForm(form)). Когда Ваш диалоговый виджет создан, Вы можете показать его как обычную форму с помощью метода Show() или ShowModal(). Как получить результат показа в последнем случае, мы расскажем чуть ниже.

Дополнительно к свойствам и методам обычных виджетов диалоговые виджеты можно разворачивать(так чтобы они занимали всю клиентскую часть родительского виджета или формы) и сворачивать(отображается только заголовок и кнопки управления), однако этот функционал может быть деактивирован в конкретной реализации виджета путем переопределения соответствующих методов. Так же в диалоговых виджетах есть два очень полезных метода. Первый это Show(). Он показывает диалоговый виджет и активирует его. И второй это ShowModal(). Он дополнительно делает виджет модальным. Наилучшим началом создания диалогового виджета является наследование его от класса CDialogBox, который уже реализует некоторую логику работы диалоговых виджетов. Соответственно сервис диалогового виджета нужно наследовать от класса CDialogBoxService.

Как было упомянуто выше, диалоговые виджеты работают как формы. Как Вы можете видеть у них есть аналогичные форме свойства и методы. Есть только одно важное отличие, касающееся методов ShowModal() формы и виджета. В случае формы метод ожидает закрытия формы, а в случае виджета - нет. В случае диалогового виджета он показывает диалоговый виджет, делает его модальным и после этого возвращает управление обратно. Очень часть требуется получить результат показа диалогового виджета после его закрытия. Так как же это можно сделать? Ответ: используя слушатель. Слушатель - это простой интерфейс, экземпляр которого может быть связан с диалоговым виджетом с помощью метода setListener() из IDialogBox. Когда в диалоговом виджете происходит действие, описанное в слушателе, виджет вызывает соответствующий метод слушателя. Если Вы посмотрите на интерфейс IDialogBoxListener, Вы увидите 4 метода-события соответствующие закрытию, сворачиванию, разворачиванию и восстановлению диалогового виджета. В случае получения результата показа диалогового виджета мы заинтересованы в методе OnClose() слушателя. Итак, чтобы получить результат мы должны реализовать интерфейс IDialogBoxListener в каком-то классе(это даже может быть класс самого виджета, однако наиболее часто он реализуется в виде отдельного небольшого дочернего класса внутри класса виджета и имеет доступ к виджету). В методе OnClose() слушателя мы можем проверить значение свойства ModalResult диалогового виджета, который вызвал метод(аргумент sender) и если оно равно ModalResult::Ok, то делаем то же что бы мы сделали если бы это была форма показанная методом ShowModal(), который вернул ModalResult::Ok. Свойство ModalResult можно получить с помощью метода getModalResult() диалогового виджета и можно установить его же методом setModalResult(). Последний по умолчанию закрывает диалоговый виджет и является предпочтительным методом окончания работы с диалоговыми виджетами. Между прочим, метод ShowModal() диалоговых виджетов устанавливает свойству ModalResult значение ModalResult::None и, если диалоговый виджет был закрыт по кнопке закрытия в заголовке, то значение свойства остается неизменным.

Так как диалоговые виджеты генерируются из форм созданных в Конструкторе Форм, их внешний вид может слегка отличаться от того как если бы это была обычная форма. Это отличие заключается в том, что обычно виджеты на диалоговом виджете выглядят слегка смещенными и клиентская часть диалогового виджета слегка шире необходимой. Для исправления этой особенности мы добавили метод AutoResize() в интерфейс IDialogBoxEx, который является интерфейсом для виджета DialogBoxEx широко используемого в качестве базового класса для Ваших диалоговых виджетов сгенерированных в Конструкторе Форм. Вызов этого метода автоматически подстраивает размер диалогового виджета под его содержимое (дочерние виджеты) и опционально может установить нужное положение. Этот метод нужно вызывать сразу после вызова метода Show() или ShowModal() диалогового виджета и делать это достаточно один раз. В дополнение, там же можно установить нужные параметры отображения(такие как цвет фона), если значения по умолчанию отличаются от стиля Вашего приложения.

Некоторые стандартные виджеты можно использовать в режиме диалоговых виджетов вместо обычных форм. Как использовать эту возможность и как создавать Ваши собственные диалоговые виджеты, а так же правильно использовать их, Вы сможете узнать в уроках Урок: диалоговые виджеты. Часть 1 и Урок: диалоговые виджеты. Часть 2.