Applies to TestComplete 14.10, last modified on May 13, 2019

The way in which TestComplete addresses windows in keyword tests and script code depends on whether the window is mapped or not (see Name Mapping). If the window is mapped, then TestComplete uses its mapped name or alias. Else, it uses the default window names.

If the Map object names automatically setting is enabled in the Name Mapping Options dialog (by default, this setting is enabled), TestComplete automatically maps window names during the test recording or at design time, when you add operations to keyword tests or when you create checkpoints. After the object name is mapped, TestComplete uses the mapped name to address this object. The default name can also be used, though.

For more information on mapping object names, see Name Mapping. The rest of this topic will describe the principles which TestComplete uses to recognize windows and to form “default” names.

The window name depends on whether the application under test is an Open Application (white-box) or non-Open Application (ordinary, black-box).

Open Applications

If the tested application is an Open Application, you can address its windows and objects using special methods provided by TestComplete: WinFormsObject, VBObject, VCLObject, SwingObject, and so on. These methods let you address the desired window by using the value specified by the application’s Name property, or by using the class name, caption, and index. The method used depends on the programming language and the development tools used to create your application. For complete information on using these methods, see the following topic:

Addressing Objects of Open Applications

Black-Box Applications

To address windows in black-box applications, TestComplete by default uses the following window attributes:

  • Window class name
  • Window caption
  • Window index

The Windows API offers several attributes meant to distinguish one window from the other, among those currently open in the system. The one it uses internally, the handle, is changed from one application to the next and, therefore, is useless. The attributes used by TestComplete - class name, caption and index - are more stable. Though each of them may change during the application run or between the sessions, their combination serves as a rather stable identifier that is suitable for any window existing in the system. The use of other properties, for example, control id (if your application supports them), is also possible. See below for more information.

Now we will describe the attributes used by default.

  • Window class name. This attribute specifies the name of the window’s class as it is registered in the operating system, for instance, msctrl_statusbar32, #32770, TForm1 or Afx:400000:b:10008:6:1027b.

    Window class name is the most stable component of a window name. It does not change during the application run. However, it is not unique for a window (it is quite possible that two or more windows have the same name) and it can change from one application run to another (these changes are typical for MFC applications). To negate the change of the class name, you can replace the varying parts of the class name with wildcard symbols (“*” and “?”). For instance, you can use “Afx:400000:b:*” instead of “Afx:400000:b:10008:6:1027b”. Without the wildcards, you would have to modify window class names in a test before each run. To specify an asterisk as part of the window class name, use two consequent asterisks.

  • Window caption. The window caption identifies the window for users. It is not unique and there can be two windows with the same caption in the system. Generally, the caption can also be changed during the execution of the application. The developer may use it to display any helpful information, for instance, the caption of a text editor usually displays the name of the edited document: “MyEditor - Document1.rtf”.

    You can use wildcard symbols (“*” and “?”) to specify caption patterns. This technique makes application testing more flexible. For example, you can specify only the constant part of the caption (“MyEditor - ”), and replace the name of the edited document with “*”. In this case, the window caption does not depend on the name of the edited document. If an asterisk is part of the caption, then to specify it, use duplicated asterisks (for example, the string “MyEditor - DocName.txt**” corresponds to the caption “MyEditor - DocName.txt*”).

    The titles of main windows often contain the application’s name followed by a hyphen and the name of the active window (or document, project, file and so on). The TestComplete recorder will automatically record the string “*” for any caption that includes a hyphen. Thus, “GraphEditor - MyPicture1.bmp” is recorded as “*”.

    Note that many windows, especially smaller ones, have no caption, that is, they all have the same caption, empty. Menus for instance, are captionless windows, and they are rather typical. Entire window classes are used without captions, making the caption useless to distinguish among siblings. In this case, to obtain a window, you should use other attributes: class name and index.

  • Index. The window’s index is more unstable than the window’s caption, but it is needed when a process or parent window has several child windows with the same caption and the same class name. The index is the current front-to-back onscreen position (similar to Z-order) of the window among windows of the same class with the same parent. Index 1 corresponds to the currently topmost window relative to other windows that have the same class name. The window index is determined by certain Windows API functions, so even if two or more windows visually have the same Z-order, they have different window indexes. To determine the index of the desired window, explore the application windows and controls in the TestComplete Object Browser.

    The index of an application window changes when other windows from the class are called onscreen or when the front-back position of this window changes.

    TestComplete may not record a window’s index when you are recording a test, if the class name and caption provide enough information for the recognition of this window.

The window name contains the word Window followed by recognition attributes enclosed in parentheses:

Window names

The window name depends on the scripting language that is used in your project. For instance, if you use JavaScript, JScript, Python or VBScript, you enclose the executable window class name and caption in quotes: Window("WndClass", "WndCaption", 1). In DelphiScript, you should use apostrophes instead of quotes, for instance, Window('WndClass', 'WndCaption', 1). In C#Script and C++Script the word Window should look like ["Window"].

The following code shows how to get access to one of the windows of the Microsoft Word process:

JavaScript, JScript

processObj = Sys.Process("winword");
windowObj = processObj.Window("OpusApp", "Microsoft Word - *", 1)

Python

processObj = Sys.Process("winword")
windowObj = processObj.Window("OpusApp", "Microsoft Word - *", 1)

VBScript

Set processObj = Sys.Process("winword")
Set windowObj = processObj.Window("OpusApp", "Microsoft Word - *", 1)

DelphiScript

var
  processObj, windowObj : OleVariant;
begin
  processObj := Sys.Process('winword');
  windowObj := processObj.Window('OpusApp', 'Microsoft Word - *', 1)
end;

C++Script, C#Script

var processObj, windowObj;
processObj = Sys["Process"]("winword");
windowObj = processObj["Window"]("OpusApp", "Microsoft Word - *, 1")

The hierarchy of windows depends on the Object tree model option of your TestComplete project. This option specifies the active object model: Flat or Tree. For complete information, see Object Tree Models. We recommend to read this topic since knowing the tree model is essential for running the tests. Keyword tests and scripts created for the Flat model will run incorrectly if the Tree model is active and vice versa.

To check the state of the Object tree model option in scripts, use the Options.Project.General.TreeModel property.

Using Custom Attributes to Obtain Window Objects

In order to identify windows, you can use not only the mentioned attributes (class name, caption, and index), but also other window attributes. For example, you can use the control identifier of a window. This identifier is an application-defined integer value associated with a window. The identifier value is returned by Windows API functions: GetWindowLong(hwndCtrl, GWL_ID) or GetDlgCtrlID(hwndCtrl). We use the term “control identifier” since this identifier is typically used to address child windows, for instance, controls on a form (controls are also windows). However, top-level windows also have identifiers.

The control identifier can be specified by a developer (for example, when they designed the dialog template in Visual Studio) or by the development tool itself (for instance, if the development tool does not support manual setting of the identifier).

To get a control’s identifier in TestComplete, you can use the ControlId property. TestComplete automatically adds this property to all windowed objects. You can check its value in the Object Browser panel.

If your application uses control identifiers, then you can use the ControlId property to find the desired control. To perform the search, use the FindChild method. TestComplete adds this method to all testing objects. The following code uses the FindChild method that returns a window object by the window’s control identifier.

JavaScript, JScript

var processObj, windowObj;
  
processObj = Sys.Process("Notepad");
windowObj = processObj.FindChild("ControlId", 133099, 1);

Python

processObj = Sys.Process("Notepad")
windowObj = processObj.FindChild("ControlId", 133099, 1)

VBScript

Set processObj = Sys.Process("Notepad")
Set windowObj = processObj.FindChild("ControlId", 133099, 1)

DelphiScript

var
  processObj, windowObj;
begin
  processObj := Sys.Process('Notepad');
  windowObj := processObj.FindChild('ControlId', 133099, 1);
end;

C++Script, C#Script

var processObj, windowObj;
  
processObj = Sys["Process"]("Notepad");
windowObj = processObj["FindChild"]("ControlId", 133099, 1);

Note: Though the control identifier seems to be a persistent window attribute, it may be unspecified (0), its value may change from one application run to another or the program may return the same identifier for two different windows. If you do not find the identifier helpful, you can use the window caption, class name and index to find the desired window.

ControlId is one of the properties you can use to find the desired object. You can use any property or combination of properties to obtain window objects. In the example above we used FindChild to search for an object by one property (ControlId). However, this method can also be used to search by a combination of property values. For more information on using the method, see the method description.

To obtain a window by ControlId or by other custom property values, you can also use the Name Mapping feature (it was mentioned at the beginning of the topic). Name mapping lets you visually specify the combination and values of the properties that will be used for recognition and to assign custom names to objects that will match the specified recognition criteria. Once you map an object, you can address this object in tests using the mapped name, rather than the object’s default name. For more information, see Name Mapping.

See Also

Object Browser Naming Notation
About Object Browser Naming Notation
Window Object
Name Mapping

Highlight search results