- •XSetNormalHints(dpy,win,&hint)
- •XDrawText() ( xDrawText16( ) ) позволяет рисовать несколько строк сразу, используя при этом разные шрифты. Каждая рисуемая единица задается структурой xTextItem.
- •IncludeInferiors — графика рисуется поверх всех подокон
- •XrmOptionDescRec pOptions [ ], Cardinal nNumOpt,
- •XtMainLoop( ) автоматически завершает программу по требованию менеджера окон.
- •VendorShell. Этот класс предназначен для того, чтобы дать возможность взаимодействия со специальными менеджерами окон.
- •XtArgVal value;
- •XtCreateWidget( ) возвращает идентификатор созданного объекта. В следующем примере создается widget класса Core, имеющий ширину и высоту равные 100 и 150 пикселов соответственно.
- •Void ActionProc (Widget prW, xEvent *prEvent, String *psParams, Cardinal *nNumParams);
- •XtActionProc proc;
- •Xt поддерживает набор специальных символов, употребляемых с модификаторами для расширения возможностей использования последних .
- •3. Обработчики событий.
- •Void HandlerProc (Widget prWidget, XtPointer pUserData, xEvent *prEvent, Boolean *pnContinue);
3. Обработчики событий.
В Xt предусмотрен еще один механизм использования процедур для выполнения определенных действий при наступлении тех или иных событий. Это механизм обработчиков событий (event handler). Он позволяет определять отдельное событие (или их группу), при наступлении которого будет вызвана указанная программой процедура-обработчик. Обработчики событий менее гибки, чем action-процедуры, но зато значительно быстрее. Последнее происходит потому, что при вызове event handler не требуется поиск процедур по соответствующим "таблицам". В этом пункте будут рассмотрены отдельные аспекты работы с event handler.
Для того чтобы программа могла использовать данную процедуру как обработчик событий, ее необходимо зарегистрировать специальным образом. Делается это с помощью процедуры XtAddEventHandler( ) или XtInsertEventHandler( ). Первая из них имеет следующий прототип:
void XtAddEventHandler (Widget prWidget,
EventMask nEventMask, Boolean nNonMaskable,
XtEventHandler pHandler, XtPointer pUserData);
Здесь prWidget — идентифицирует объект, к которому будет добавлена процедура- обработчик pHandler. nEventMask — комбинация флагов, задающая события, в ответ на которые будет вызываться регистрируемая процедура. Третий аргумент в процедуре XtAddEventHandler( ) - это логическая переменная равная True, если обработчик будет вызываться для событий, которые всегда посылаются программе. Это MappingNotify, ClientMessage, SelectionClear, SelectionNotify, SelectionRequest (заметим, что последние три события связаны с механизмом общения между программами через системный буфер (clipboard), описание которого выходит за рамки настоящего издания). Наконец, последний аргумент процедуры — pUserData — это указатель на данные, передаваемые в обработчик при его вызове. Если таковых нет, то аргумент должен быть равен NULL.
Заметим, что для одного и того же события в списке обработчиков может быть зарегистрировано несколько функций. XtAddEventHandler( ) добавляет функцию pHandler в конец этого списка.
Процедура, используемая как обработчик событий, должна иметь следующий прототип:
Void HandlerProc (Widget prWidget, XtPointer pUserData, xEvent *prEvent, Boolean *pnContinue);
Здесь первый аргумент указывает на объект, для которого заказана реакция на событие. Второй аргумент указывает на данные, передаваемые в обработчик из программы. Он равен аргументу pUserData, задаваемому при вызове функции XtAddEventHandler(). Третий аргумент — указатель на событие, инициировавшее обращение к event handler. И, наконец, последний аргумент указывает, следует ли системе вызывать следующие зарегистрированные для данного события обработчики или нет. Перед вызовом процедуры система делает этот параметр равным True. Если программа не желает, чтобы событие обрабатывалось дальше, значение переменной, на которую указывает pnContinue, должно быть изменено на False.
Функция XtInsertEventHandler( ) также заносит процедуру в список обработчиков того или иного события, но она позволяет поместить ее в произвольное место списка.
XtInsertEventHandler( ) имеет следующий прототип:
void XtInsertEventHandler (Widget prWidget,EventMask nEventMask, Boolean nNonMaskable,
XtEventHandler pHandler, XtPointer pUserData, XtListPosition nPosition);
Первые пять аргументов полностью идентичны описанным выше для процедуры XtAddEventHandler(). Последний аргумент — указывает, в какое место списка обработчиков будет помещена функция pHandler. Аргумент может принимать одно из двух предопределенных значений: XtListHead, которое означает, что функция будет помещена в голову списка и, следовательно, будет вызываться раньше любого event handler, зарегистрированного для данного объекта и события. Второе значение — XtListTail, которое указывает, что функция будет помещена в конец списка и будет вызываться после всех зарегистрированных процедур.
Как мы упоминали ранее, для одного и того же события можно зарегистрировать несколько event handler, но при этом каждая функция с одинаковыми параметрами pUserData может встретиться в списке только один раз. Однако, если та же самая функция регистрируется с помощью XtInsertEventHandler( ), то она будет добавлена в список, но передвинута либо в конец списка либо в его начало.
Вызов процедур XtAddEventHandler() и XtInsertEventHandler() может осуществляться до и после реализации соответствующего widget.
Ниже приводится фрагмент кода, в котором с помощью функции XtAddEventHandler( регистрируется функция-обработчик, которая будет вызываться при изменении фокуса ввода для данного widget. Ее можно использовать для выполнения определенных действий при наступлении соответствующих событий.
. . . . . . .
void CheckFocus (Widget prWidget, XtPointer pUserData,XEvent *prEvent)
{
. . . . . . . .
if (event->type == FocusIn)
{
/* Выполняются действия при получении фокуса ввода */
. . . . . . .
}
else
{
/* Выполняются действия при потере фокуса ввода */
. . . . . .
}
}
. . . . . . . .
main (int argc, char *argv)
{
. . . . . . . .
XtAddEventHandler (prCoreWidget, FocusChangeMask, False,(XtEventHandler) CheckFocus, NULL);
. . . . . . . .
}
Когда процедура-обработчик становится не нужной, ее можно удалить из списка. Для этого можно использовать процедуру
void XtRemoveEventHandler (Widget prWidget,EventMask nEventMask, Boolean nNonMaskable,XtEventHandler pHandler, XtPointer pUserData);
Она имеет те же самые аргументы, что и процедура XtAddEventHandler(). Если параметры в вызовах этих процедур не совпадают, то удаления указанного обработчика не произойдет. Так происходит, например, если параметр pUserData при вызове XtRemoveEventHandler() не совпадает с заданным при обращении к XtAddEventHandler().
Основы X Toollkit
Что такое объекты Xt.
Как мы уже упоминали ранее, пакет представляет собой базу для создания управляющих элементов (widget). В смысле Xt widget - это просто структура данных, поля которой включают идентификатор самого элемента, идентификатор его окна, если таковое имеется, и многое другое. Атрибуты такого объекта называются ресурсами. Ресурсами widget могут быть, например, цвет фона его окна, шрифт выводимого текста, цвет границы окна и т.д.
Каждый объект принадлежит к одному из предопределенных классов (widget class). Класс можно рассматривать как множество экземпляров (объектов), имеющих одинаковые характеристики. Классы Xt образуют иерархию.
Во время работы программа создает сами объекты (экземпляры классов - widget). Они образуют совокупности, каждая из которых также представляет собой некоторую иерархию. Каждая такая иерархия называется деревом объектов (widget tree). Корнем дерева обязательно является widget, принадлежащий к одному из подклассов специального класса - Shell (в дальнейшем, говоря о таких объектах, мы иногда будет употреблять термин "shell-объект" или "shell-widget"). Если среди двух widget A и B дерева объектов первый ближе к корню, чем второй, то A является родительским объектом ("родителем") для B, а B есть подобъект (или "дочерний" объект, иногда также мы будем использовать термин "потомок") для A. Таким образом, shell-объект является родительским widget для всех остальных widget данного дерева объектов. Именно он осуществляет взаимодействие программы и менеджера окон.
Описанная иерархия widget соответствует взаимосвязи их окон, что является свойством X Window. Кроне этого, на объекты накладывается и другая иерархическая структура. Дело в том, что во время функционирования одни объекты могут управлять другими. Например, если объект A имеет два подобъекта B и C, то при изменении размеров A последний может автоматически перестроить B и C. Для того, чтобы это могло осуществиться, между widget устанавливается связь - связь "по управлению". Каждый объект может иметь один или несколько "управляемых" (managed) подобъектов.
Теперь рассмотрим, как программа, использующая Xt, вэаимодействует с widget и X Window System. Предусмотрены три механизма.
Первый из них - процедуры обратного вызова (callback-процедуры или просто callback). Для любого класса определена совокупность действий, на которые должны реагировать принадлежащие ему объекты. Так, для любого класса предусмотрена реакция на уничтожение widget. Когда действие производится, происходит вызов либо стандартной функции Xt либо одной или нескольких процедур, предоставляемых программой. Такие функции и называются callback-процедурами.
Второй способ взаимодействия - action-процедуры. Программа может заказать реакцию на то или иное событие (или группу событий), приходящее от X. Если событие происходит, Xt осуществляет поиск и вызов соответствующей функции.
Третий механизм - обработчики событий (event handler). Этот способ аналогичен предыдущему, только более быстр в ущерб гибкости. Он позволяет реагировать только на единичные события, но не на их последовательности. Более подробно об указанных механизмах и способах их использования будет рассказано ниже.
