3.2.3. Управление объектами.

    Для создания любого объекта, кроме shell-widget, можно использовать процедуру

Widget XtCreateWidget (String psName, WidgetClass pClass, Widget prParent, ArgList arArgs, Cardinal nNumArgs);

    Здесь первый аргумент - это произвольная строка, содержащая имя создаваемого widget. Оно используется для получения значений ресурсов объекта из базы данных ресурсов, а также для других целей. Второй аргумент задает класс widget. Третий аргумент - это родительский объект, который должен быть уже создан. В качестве последнего может быть указан shell-widget или любой объект, который может иметь подобьекты (принадлежит классу Composite или его подклассам). Четвертый и пятый аргументы XtCreateWidget( ) определяют значения дополнительных ресурсов, задаваемых при создании widget. Тип ArgList определен в файле "Intrinsic.h" следующим образом:

typedef struct { String name; XtArgVal value; } Arg, *ArgList;

    Здесь name представляет предопределенную строковую константу, задающую имя соответствующего ресурса (например XtNwidth). value - это значение атрибута. Это поле имеет специальный тип XtArgVal, определение которого является системно-зависимым. Как правило, размер данного поля достаточен для того, чтобы поместить туда целое число или указатель. Но его не достаточно, например, для задания чисел типа double. Общее правило таково: если размер значения ресурса меньше sizeof (XtArgVal), то в value содержится непосредственно само значение, в противном случае поле value есть адрес области памяти, содержащей значение ресурса. Если аргументы arArgs и nNumArgs в XtCreateWidget( ) не используются, то они должны быть равны NULL и 0 соответственно.

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

    XtCreateWidget( ) возвращает идентификатор созданного объекта. В следующем примере создается widget класса Core, имеющий ширину и высоту равные 100 и 150 пикселов соответственно.

. . . . . . . Arg aReserv [ ] = { { XtNwidth, (XtArgVal) 100 }, {XtNheight, (XtArgVal) 150 }, }; /* Ресурсы и их значения */ Widget prShellParent; /* Родительский объект */ Widget prCoreWidget; /* Идентификатор объекта */ . . . . . . . prCoreWidget = XtCreateWidget ("core", widgetClass, prShellParent, aReserv, XtNumber (aReserv)); . . . . . . .

Здесь XtNumber( ) - макрос, определяющий размер массива фиксированной длины.

    Заметим также, что значение ресурса в массиве aReserv должно иметь тип, соответствующий данному ресурсу.

    Вместо создания статического массива ресурсов можно заполнять его динамически, используя макрос XtSetArg( ). Например, предыдущий фрагмент можно было бы переписать следующим образом:

. . . . . . . Arg aReserv [5]; /* Используется для задания ресурсов */ int i = 0; Widget prShellParent; /* Родительский объект */ Widget prCoreWidget; /* Идентификатор объекта */ . . . . . . . XtSetArg (aReserv [i], XtNwidth, 100); i++; XtSetArg (aReserv [i], XtNheight, 150); i++; prCoreWidget = XtCreateWidget ("core", widgetClass, prShellParent, aReserv, i); . . . . . . .

    В X11R4 и выше задавать ресурсы при создании widget можно более удобно. Для этого надо использовать процедуру

XtVaCreateWidget (String psName, WidgetClass prClass, Widget prParent, . . .);

    На месте многоточия при вызове процедуры должен стоять завершающийся нулем список пар: "имя ресурса, его значение". Ниже приведен пример применения XtVaCreateWidget( ).

. . . . . . . Widget prShellParent; /* Родительский объект */ Widget prCoreWidget; /* Идентификатор объекта */ . . . . . . . prCoreWidget = XtCreateWidget ("core", widgetClass, prShellParent, XtNwidth, 100, XtNheight, 150, NULL); . . . . . . .

    Каждый родительский widget (за исключением shell-widget) управляет своими "потомками", т.е. распоряжается их расположением, размером, получением фокуса ввода и т.д. Например, в OSF/Motif некоторые объекты располагают свои "дочерние" widget в ряды и колонки, другие группируют "потомков" в "блоки" и т.д. Для того, чтобы "дочерний" мог управляться своим "родителем", его необходимо включить в соответствующий список. Для этого используется процедура

void XtManageChild (Widget prWidget);

    Здесь единственный аргумент идентифицирует widget, которым будет управлять "родитель".

    Xt предусматривает более удобную процедуру XtCreateManagedWidget( ) (XtVaCreateManagedWidget( )), которая создает widget и после этого автоматически вызывает функцию XtManageChild( ). Аргументы указанной процедуры полностью идентичны аргументам процедуры XtCreateWidget( ) или XtVaCreateWidget( ). Заметим, однако, что иногда более удобно создать сначала группу "дочерних" widget, а затем сразу всех включить в список управляемых (managed) объектов. Для этого можно воспользоваться функцией

void XtManageChildren (WidgetList prWidgetChildren, Cardinal nChildrenNumber);

    Здесь первый и второй аргументы задают массив подобъектов и число элементов в этом массиве соответственно.

    Процедура XtRealizeWidget (Widget prWidget) создает окна заданного widget, его управляемых подобъектов и показывает их на экране. Этот процесс называется "реализацией" объекта. Заметим, что нельзя реализовать widget, если это не сделано предварительно с его "родителем".

    Если объект реализован, то вызов функции XtManageChild( ) для любого его подобъекта автоматически реализует последний.

    Целый ряд процедур Xt позволяют получать различную информацию о widget. Среди таких процедур укажем следующие.

    Процедура XtIsRealized (Widget prWidget) позволяет проверить, реализован данный объект или нет.

    Процедура XtDisplay (Widget prWidget) возвращает указатель на X структуру данных типа Display, которая используется данным widget.

    Процедура XtScreen (Widget prWidget) возвращает для заданного объекта указатель на X структуру данных типа Screen.

    Процедура XDestroyWidget (Widget prWidget) используется для уничтожения заданного widget и всех его "потомков": указанная процедура освобождает все ресурсы, используемые уничтожаемыми объектами.