Xt поддерживает несколько способов работы с окнами widget. Так программа, используя процедуры, предоставляемые Xt, может показать окно, установить для него тот или иной режим работы, и закрыть окно, когда последнее становится не нужным. В основном эти процедуры используются для создания "всплывающих" (pop up) меню и диалогов. Рассмотрим кратко эти способы.
Первый способ. В Xt есть три предопределенные процедуры для показа окна объекта и одновременного задания режима обработки событий (Xt grab mode). Может быть сохранен нормальный процесс рассылки событий между объектами приложения, но может быть сделано и так, что Xt будет направлять события, возникающие в результате действий пользователя, в widget независимо от того, в каком объекте они происходили. Режим обработки событий называется в Xt "режимом захвата" (grab mode).
"Захват" может быть двух типов: исключительным (exclusive) и неисключительным (nonexclusive). Разница между ними проявляется, когда программа создает, например, многоуровневое меню. Рассмотрим следующий пример. Пусть мы открыли первое подменю, затем второе, а после него третье. Теперь пользователь нажал на кнопку мыши. Если режим "захвата" exclusive, соответствующее событие будет передано widget, представляющему третье подменю. Если режим "захвата" nonexclusive, то оно будет послано тому подменю, в котором находится курсор мыши. Если же курсор не попал ни в одно подменю, то событие опять таки получит последний (третий) widget.
Процедуры, отображающие объект и задающие режим обработки событий, следующие: XtCallbackNone( ), XtCallbackExclusive( ), XtCallbackNonexclusive( ). Все они имеют стандартный набор параметров, определенный в Xt для процедур обратного вызова. Идентификатор объекта, окно которого должно быть показано на экране, передается через аргумент pUserData.
Первая процедура используется для показана окна widget и не меняет способ обработки событий.
Вторая и третья процедуры используются для отображения окна widget и одновременного задания режимов exclusive и nonexclusive соответственно.
Ниже приводится фрагмент кода, содержащий пример использования одной из перечисленных выше процедур. Здесь мы используем объект PushButton ("нажимаемая кнопка") из библиотеки OSF/Motif (см. главу 4).
. . . . . . . . . . . . .
main (int argc, char **argv)
{
Widget prShellWidget; /* Показываемый shell-объект */
Widget prPushButton; /* "Нажимаемая кнопка" */
. . . . . . .
prShellWidget = XtCreatePopupShell ( . . . );
prPushButton = XtCreateWidget ( . . .);
. . . . . . .
XtAddCallBack (prPushButton, XmNactivateCallback,
XtCallbackExclusive, prShellWidget);
. . . . . . .
}
. . . . . .
|
Цель данного кода - показать "всплывающее" (pop up) окно при "нажатии" на кнопку. Для этого мы сначала создаем "всплывающий" shell-объект с помощью процедуры XtCreatePopupShell( ) и заносим стандартную процедуру XtCallbackExclusive( ) в список callback кнопки prPushButton. Этот список соответствует ресурсу XmNactivateCallback (см. Приложение 3). Занесенные в него процедуры вызываются в ответ на "нажатия" на объект с помощью мыши или клавиши клавиатуры. Последний параметр функции XtAddCallBack( ) позволяет нам сообщить стандартной процедуре XtCallbackExclusive( ), окно какого widget должно быть показано на экране.
Для закрытия окон widget, используется callback-процедура XtCallbackPopdown( ). При ее вызове параметр pUserData должен указывать на структуру типа XtPopdownId, определяемую следующим образом:
typedef struct {
Widget shell_widget;
Widget enable_widget;
} XtPopdownIdRec, *XtPopdownId;
|
Здесь первое поле определяет shell-объект, который будет закрыт, второе поле задает объект, которой инициировал его показ.
Ниже приводится фрагмент, содержащий пример использования описанной процедуры.
. . . . . . .
Widget prShellWidget, prPushButton;
XtPopdownIdRec rRec;
. . . . . . .
main (int argc, char **argv)
{
. . . . . . .
prShellWidget = XtCreatePopupShell ( . . . );
prWidget = XtCreateManageWidget ( . . . );
. . . . . . .
rRec.shell_widget = prShellWidget;
rRec.enable_widget = prPushButton;
. . . . . . .
XtAddCallback (prPushButton, XmNactivateCallback,
XtCallbackPopdown, &rRec);
. . . . . . .
}
. . . . . . .
|
Второй способ. Xt предусматривает две специальных action-процедуры XtMenuPopup( ) и XtMenuPopdown( ), которые применяются для отображения и закрытия окон объектов соответственно. Имена процедур могут быть использованы в "таблицах трансляции" программы. Функция XtMenuPopup( ) имеет следующий прототип:
void XtMenuPopup (String shellname);
|
Здесь аргумент процедуры используется для задания имени отображаемого shell-объекта. Данная action-процедура может быть определена в "таблице трансляции" для следующих событий: ButtonPress, KeyPress, EnterWindow.
Процедура XtMenuPopdown( ) аналогична описанной выше функции только используется для закрытия указанного shell-объекта.
Третий способ. Xt предусматривает для непосредственного отображения на экране и закрытия окон widget также и отдельные процедуры XtPopup( ), XtPopupStringLoaded( ) и XtPopdown( ).
Первая процедура используется для непосредственного размещения на экране окна widget и имеет следующий прототип:
void XtPopup (Widget prShellWidget,
XtGrabKind grabmode);
|
Здесь первый аргумент задает shell-объект. Второй аргумент определяет режим обработки событий. Возможные его значения следующие:
XtGrabNone | - нормальный режим работы; |
XtGrabExclusive | - исключительный (exclusive) "режим захвата"; |
XtGrabNonexclusive | - неисключительный (nonexclusive) "режим захвата". |
Вторая функция - XtPopupStringLoaded( ) - используется также для отображения окон и отличается от XtPopup( ) в частности тем, что автоматически задает режим обработки событий exclusive. Функция имеет следующий прототип:
void XtPopupStringLoaded (Widget prShellWidget);
|
Здесь аргумент аналогичен первому аргументу предыдущей процедуры.
Третья процедура используется для закрытия окна объекта и имеет прототип, аналогичный предыдущей функции.
Заметим, что, как правило, каждое множество widget (например, OSf/Motif, OPEN LOOK и др.) имеет свои удобные процедуры для создания меню и диалогов, поэтому мы не будем более подробно останавливаться на данном вопросе.