Working with the TestStand Simple User Interface - LabWindows/CVI


TestStand includes simple user interface examples that demonstrate the concepts of TestStand user interface development. You can also use these examples as a basis for creating your own custom user interfaces. These examples demonstrate the following basic TestStand functionality:
  • Opening and executing sequence files
  • Viewing the status of running executions
  • Breaking and erminating executions
  • Viewing reports for completed executions
The first section of this document provides a detailed look at how the Simple User Interface functions. The next section provides instructions for implementing common customizations to the Simple User Interface.

Guide to the Simple User Interface

The simple user interface implements the following execution states. Refer to the topics below for the functional details of each state.

  • Initializing
  • Configuring Callbacks to Handle TestStand Events
  • Connecting Manager controls to Visible controls
  • Starting TestStand
  • Waiting for Events
  • Shutting Down
  • Handling Errors

This user interface example is located in the following directory:

 <TestStand Public>\UserInterfaces\Simple\CVI\TestExec.cws

For similar information on LabVIEW or LabWindows/CVI based implementations of the TestStand simple user interface, see the following documents:


In the initialization phase of execution, the UI performs typical startup tasks:

  • Initializing the CVI RuntimeEngine
  • Loading the user interface

Once complete, the interface calls the SetUpActiveXControls function, which implements the remainder of initialization, connects manager controls to visible controls, and configures callbacks to handle TestStand events. In this function, the GetObjHandleFromActiveXCtrl() function obtains the ActiveX handles in the gMainWindow global.

The user interface maintains a gMainWindow global variable, which contains ActiveX handles for the following TestStand UI Controls:

  • Manager UI controls. These invisible controls handle many of the UI functions. Refer to the Manager UI Controls help topic for more information about the purpose of these controls.
  • Visible UI controls. These controls display TestStand information to the user but require a connection to a manager control in order to function. The connections are created in the Connecting Manager controls to Visible controls execution state. Refer to the Visible UI Controls help topic for more information about the available visible controls.
  • Other references.  These references  are used by code in the user interface, such as the TestStand Engine reference,  and are stored in the gMainWindow structure to ensure that the references can be accessed in all parts of the UI.

Because the gMainWindow is an instance of the MainPanel Type definition, you can easily add new references to the type definition when making additions to the UI.

 Configuring Callbacks to Handle TestStand Events

TestStand user interface controls generate events to notify an application of user inputs and application events and allow a user interface to respond when application events occur. 

In the SetupActiveXControls function, the UI registers callback functions to execute when these specific TestStand Events occur using the Event Callback Registration functions in the NI TestStand UI Controls Library. 

These registration functions allow you to specify callback functions that execute when a specified TestStand event occurs. For example, the registration function below specifies that the ApplicationMgr_OnExitApplication() function should execute when the ExitApplication event is generated:

errChk( TSUI__ApplicationMgrEventsRegOnDisplaySequenceFile(

gMainWindow.applicationMgr,              //control generating the event

ApplicationMgr_OnDisplaySequenceFile,    //Function to call when event occurs





The callback function has a specific prototype based on the particular event being handled. The ApplicationMgr_OnExitApplication function is shown below.

// the ApplicationMgr sends this event to request that the UI display a particular sequence file

HRESULT CVICALLBACK ApplicationMgr_OnDisplaySequenceFile(

CAObjHandle caServerObjHandle,

void *caCallbackData,

TSUIObj_SequenceFile file,

enum TSUIEnum_SequenceFileDisplayReasons reason)


       int    error = 0;

       tsErrChk( TSUI_SequenceFileViewMgrSetByRefSequenceFile(


&errorInfo, file));



       return error < 0 ? E_FAIL : S_OK;


The Simple user interface example registers the following events:

Event Name Event Description Callback VI Functionality
DisplaySequenceFile Occurs when you open a sequence file directly or when TestStand sends a UIMsg_OpenWindows event. Sets a newly opened sequence file as the current sequence file.  The newly opened file is displayed in the Sequence File combo box.

Occurs when the application has completed the shutdown process.


Generates the Quit Application User Event, which allows the User Interface to begin shutdown. This user event is created in the Register Event Callbacks state immediately before the Register Event Callback function.



DisplayExecution Occurs when a visible execution starts, when an execution breaks, or in response to a UIMsg_OpenWindow or UIMsg_GotoLocation user interface message. Use the reason parameter to find out why this event was called. Sets the current execution to be the execution in which the event is generated, typically.  The Execution View control displays the execution.
Wait Occurs when the application is performing lengthy tasks. Sets the mouse cursor to the wait cursor for lengthy operations, and sets the cursor back to the default cursor when the lengthy operation completes.
ReportError Occurs when an error is reported. This event notifies the application of errors that occur while the user operates connected controls. Calling the ApplicationMgr.RaiseError event also calls the ReportError event. Reports errors generated by TestStand in a dialog.


In the simple user interface example, the ApplicationManager control generates each specified control, but other controls generate events as well.Refer to the Handling Events help topic for more information about using the Event Registration Functions to handle TestStand events.

Connecting Manager Controls to Visible Controls

In the SetUpActiveXControls funtion, the manager UI controls are connected to the visible controls  to specify the functionality of the visible control. Functions of the manager controls implement the connections For example, the following statement connects the Login/Logout button to the manager control and specifies that the button should trigger the login/logout command. 

tsErrChk( TSUI_ApplicationMgrConnectCommand(gMainWindow.applicationMgr,


gMainWindow.loginLogoutBtn,              //control reference

TSUIConst_CommandKind_LoginLogout,       //type of command to connect





Many connection functions are available for each manager control depending on the desired functionality of the visible control. Refer to the subtopics of the Connecting Manager Controls to Visible Controls help topic for more information about the available types of connections.

When using a connectCommand function, as in the case of the login/logout button, you must specify a commandKind that represents the specific command that will be associated with the visible control. In this case, the function call specifies the commandKind TSUIConst_CommandKind_LoginLogout, which gives the Login/Logout button its specific functionality. Refer to the CommandKinds Enumeration help topic for more information about available commandKinds.

Once a visible control is connected to a manager control, no further code is necessary for the control to function.

Starting the Application

After the SetupActiveXControls function completes, the main function calls the TSUI_ApplicationMgrStart function.   This function initializes the TestStand engine and launches the user interface. At this point, all visible controls have been connected to manager controls, and TestStand events have been registered to callback functions. After starting, TestStand displays the user interface and calls the RunUserInterface(), which does not return until the QuitUserInterface() function is called. The remainder of the user interface execution waits for TestStand and CVI events.

Waiting for Events

After starting the TestStand Application manager, the user interface waits for events to occur and handles them using the registered callback functions. 

In addition to TestStand event functions, the user interface handles two CVI events. For example, the MainPanelCallback Handles the EVENT_CLOSE event, which occurs when the user closes the panel.

int CVICALLBACK MainPanelCallback(

int panel,

int event,

void *callbackData,

int eventData1,

int eventData2)


       switch (event)


              case EVENT_CLOSE:          // user clicked on window close box

                     ExitApplication();   // this function displays error, if any



       return 0;


In the ExitApplication function,calling the TSUI_ApplicationMgrShutdown function starts the shutdown process. If the function returns a value of “ True,” the TestStand engine has completed shutdown and the shutdown case can execute. Otherwise, the user interface must continue to handle events until the Exit Application Event User Event is generated.

The following table describes the two CVI events handled by this event structure::

Event Name Event Description Functionality when the event occurs
MainPanelCallback - EVENT_CLOSE event

Occurs when the user tries to interactively close the user interface by selecting the Close item in the File menu or by clicking the close glyph on the window border. 


Calling the TSUI_ApplicationMgrShutdown function starts the shutdown process. If the function returns a value of “True,” the TestStand engine has completed shutdown and the QuitUserInterface() is called to close the application.  Otherwise, the application closes after the ExitApplication TestStand event is handled.


MainCallback - EVENT_END_TASK event Occurs when Windows shutsdown or when the user selects Close from the context menu on the application's task bar item. The behavior is similar to EVENT_CLOSE but the application closes when the machine is shutting down, even if TestStand shutdown is incomplete.

Shutting Down

Calling the ApplicationManager Shutdown method starts the shutdown process. If the method returns a value of “True,” the TestStand engine has completed shutdown and the shutdown case can execute. Otherwise, the UI continues handling events until the ExitApplication TestStand event is generated, which indicates that the engine has been shut down.

Once the TestStand engine has completed shutdown, the following operations occur:

  1. The TestStand engine reference is closed.
  2. The QuitUserInterface function is called, allowing the UI to finish executing.

Error Handling

Error information in the simple user interface example is tracked by wrapping TestStand UI functions with the tsErrChk macro, which checks for any errors that occurred in the function call. This macro also translates the ActiveX error information into an error code and description. 

If an error occurs, the execution moves to the “Error:” label to handle the error. In this section, the DisplayError function is called to display the error to the user using the TestStand Utility function TS_DisplayError.

Common Customizations the Simple User Interface

Adding New TestStand Controls

You can customize the user interface by adding additional UI controls. In order to make your new controls function, you must connect them to a manager control. 


To add a new control to the simple user interface, follow the steps below. In this example, you will create a new button to launch the TestStand station options window.

  1. In the TestExec.uir file, add a TestStand button Control to the panel from the TestStand palette. In the list of controls, select the desired TestStand UI control. Refer to the Visible Controls help topic for more information about each control. 
  2. Modify the MainPanel struct to include a reference to the new control:

typedef struct


       Int panel;

       CAObjHandle   engine;


       // ActiveX control handles:


       CAObjHandle loginLogoutBtn;

       CAObjHandle exitBtn;

       CAObjHandle stationOptBtn;    //new button

} MainPanel;

  1. In the SetupActiveXControls function, call the GetObjHandleFromActiveXCtrl function to add your control to the gMainWindow struct.

errChk( GetObjHandleFromActiveXCtrl(gMainWindow.panel,




  1. In the SetupActiveXControls function, call the desired connection function to connect the control to a manager control. Refer to the Connecting Visible Controls to Manager Controls help topic for more information about the available connections.

tsErrChk( TSUI_ApplicationMgrConnectCommand(

gMainWindow.applicationMgr,                     //manager control


gMainWindow.stationOptsBtn,              //visible control

TSUIConst_CommandKind_ConfigureStationOptions, //command type





Handling Additional Events

To initiate an action in response to a TestStand event, create a new callback function and register it using an event registration function. Follow the steps below to create a new callback to handle a TestStand event. In this example, you will create a callback to handle user generated UIMessages.

  1. In the SetupActiveXControls function, call the desired  Event Registration function. Refer to the UI Controls API Reference help topic for more information about what events are available for each UI control.

errChk( TSUI__ApplicationMgrEventsRegOnUserMessage(


ApplicationMgr_OnUserMessage,     //callback function to handle event

NULL,                             //custom callback data



Note: To access custom data in the callback, pass it into the CallbackData parameter of the registration function or use a global variable.


  1. Create a new callback function to handle the event. The name of the function must match the name specified in the Event Registration function. Refer to the help topic for the registration function to find the correct prototype for the callback function.

// handles custom UI messages - UI messages with event code greater than UserMessage_Base (10000)

HRESULT CVICALLBACK ApplicationMgr_OnUserMessage(CAObjHandle caServerObjHandle, void *caCallbackData, TSUIObj_UIMessage  uiMsg)


       enum TSEnum_UIMessageCodes uiMsgEvent;

       int           error = 0;


       tsErrChk(TS_UIMessageGetEvent(uiMsg, &errorInfo, &uiMsgEvent));

       switch (uiMsgEvent)


              case (10001):

                     //Code to handle custom UI Message



       return S_OK;




       return S_OK;


Adding Native Environment Controls

To add native CVI controls to the user interface, create the control in the .uir file and use a control callback function to add functionality, as you would in a typical CVI user interface application.  Additionally, you can implement some TestStand functionality with native controls using the GetCommand and Command.Execute methods, as shown in the example below. Any of the manager controls can call the GetCommand method to access the connections created by each control.

int CVICALLBACK configureAdaptersCallback (int panel, int control, int event,

              void *callbackData, int eventData1, int eventData2)


       TSUIObj_Command newCommand = NULL;

       int                  error = 0;   


       switch (event)


              case EVENT_COMMIT:

                     //create a new command object to launch the adapter dialog







                     //execute the command

                     tsErrChk(TSUI_CommandExecute(newCommand, &errorInfo, VTRUE));






              return error;



National Instruments recommends using the Visible UI controls whenever possible to access the built-in features of these manager controls.


Was this information helpful?