The TabEx widget is a container for non-modal forms that overlay each other as they are made active. Each contained form is represented as a tab. The TabEx widget is highly customizable, allowing extensive control over the appearance and behavior of the tabs.



Logical Widget Name:


Physical Widget Name:


Standard Triggers:

Value Changed

Extended Triggers:

Resized, onTabButton

Supported in Grid?:


Supports MSAA? : Yes, including its child tabs and the tab strip scrollbars.

Widget Properties

If no properties are set, the tabs are displayed according to the Windows theme.


The TabEx widget provides a way of organizing data or organizing an application. You can use it to present multiple instances of the same form, but with different data retrieved. Or you can display instances of completely different forms. Unlike the Tab widget, it provides many properties that enable you to customize its appearance and behavior.


The TabEx widget is more flexible and customizable than the Tab widget. You can switch all existing Tab fields to use the TabEx widget by assigning the physical widget utabex to the logical widget Tab in the .ini file. For example:

;Tab=utab   ; old mapping
Tab=utabex  ; new mapping

Defining and Activating Contained Forms in Tabs

The collection of forms is defined by the field's ValRep, and each form called by the tab widget must be explicitly activated using an activate statement. You can use the Execute trigger of the parent form where the tab widget is drawn to initially activate all the forms that are called as tab pages. For example:

;Execute trigger of form containing the tabex widget
  ; Create ValRep Callout 1
  putitem/id $valrep(TABFLD), "mail", "mail.png!Mail"  
  putitem/id $valrep(TABFLD), "contacts", "contacts.png!Contacts"
  putitem/id $valrep(TABFLD), "calendar", "calendar.png!Calendar"

  ; Create instances of contained forms Callout 2
  newinstance "MAILLST", "mail"
  newinstance "CONTACTLST", "contacts"
  newinstance "AGENDA", "calendar"

  TABFLD = "mail" Callout 3
  activate TABFLD Callout 4
  1.  Create the ValRep of the tab field. The Representation part of each ValRep item can contain text, both an image and text, or just an image. For more information, see ValRep List Syntax.
  2.  Create a ne instance of each contained form in the ValRep.
  3.  Assign one of the instances to the tab field.
  4.  Activate the instance specified by the tab field.
Note:  To test a tab widget, you need to create a startup shell that activates the form containing the tab widget. If you run this form in test mode in the development environment, you can check the appearance of the tabs, but the contained forms are not displayed.

Contained Forms

The forms activated by the tab widget must have the Window Type set to Contained Form. This property automatically defines a form as non-modal and attached, and overlays the previous form.

When defining and testing a tab widget, take into account the following points:

  • If you use the syntax definition NED to disable a contained form, the tab label is not dimmed. This is because the contained form is separate from the tab label.

  • You cannot make a contained form non-editable from the tab widget definition.

  • You cannot test a contained form individually. If you want to test a contained form separately from the tab widget, you must change the window type of the form from Contained Form to the relevant window type.

  • The contained forms in the tab widget are non-modal attached forms, so if a user changes a field or key field in a contained form, and then edits a field on the parent form, the Leave Modified Key and Leave Field triggers are not activated. This is because the field does not lose focus and therefore cannot be validated. If there is an error, for example an illegal duplicate key is created, it will not be detected until the user tries to store the occurrence in the database.

    To force field validation for each entity in a contained form, in the Form Loses Focus trigger, assign the primary and candidate key fields to themselves and write an explicit validateocc or validatekey statement. This forces Uniface to fill the field with values, so that you can explicitly perform the field validation. For example:

    ;trigger FormLosesFocus 
      PK1 = PK1
      PK2 = PK2
  • Uniface supports a two-phase close for Accept and Quit actions in attached component instances, and thus in contained forms. (By definition, a contained form is an attached instance.)

    Depending on the original request (Accept or Quit), the Accept or Quit operation or trigger of all involved tab instances is fired, starting with the child instances and then from the bottom up to the instance that originated the close request. If one of the involved instances leaves the Accept or Quit trigger with a negative value in $status the close sequence is canceled without closing any of the involved instances, even if some instances have already returned 0 in $status. Proc code in the Quit/Accept trigger of every instance determines whether the instance agrees to the close request.

  • The CLOSECONTEXT initialization setting determines whether a Quit request is sent to the contained form or the parent form when the Close caption button is clicked.

  • Panels are not shown in a contained form. If the form containing the tab widget has a panel, that panel will be used by the contained form. However, for user-defined buttons in the panel to work in the contained form, the operations also need to be defined in the Operations trigger of the individual contained forms.

Tab Size

It is good practice to let the labels in the tab widget define the size of the tab, rather than using the Tab Width property. This ensures that the tab widget design is independent of the screen resolution.

If you are using an image in the tab, you can use an image with a small width which is stretched to fill the tab according to the label size.

Widget Size

The size of the TabEx widget can be changed if its Attach property is set. After the parent form is resized, the Resized extended trigger is fired, with the new widget dimensions as input parameters. You can add code to this trigger that displays a different form that is more appropriate to the new size.


By default, the tab strip is displayed as a single horizontal line. If the sum of the tab widths exceeds the width of the tab widget, scroll buttons are displayed to enable the user to scroll tabs into view. Each click on a scroll button moves the tab strip exactly the width of the left-most tab in the horizontal tab strip.