DynamicWindow Sample

Description
This is a relatively complex sample script that uses Phantom's built-in functions to create a set of User-Defined functions. The new functions, 'FindChild' and 'BuildWindow', are useful for automating highly dynamic windows, such as Internet Explorer, whose structure can change with each new instance or can be different depending on the machine. These functions can be placed in a .fun file and loaded using the 'include' keyword, or placed directly in a script.

The FindChild user-defined function finds a child window with a specified tag and class. This recursively searches all windows, so that any child (not just direct descendants) with the tag and class is found.

The BuildWindow user-defined function builds a window variable with the full set of children added as member variables, similar to those created when loading a Window Declarations File. This is also called recursively to add all children, not only direct descendants.

A simple example automating Internet Explorer with the new functions is presented. Note that version 7 of Internet Explorer was used for this script. While the user-defined functions are independent of the target application, the sample script at the end may need to be modified if Internet Explorer 7 is not used.

This script illustrates the use of the following Phantom features:

- Child Window functions
- Window Class and Tag variables
- String functions
- User Defined Functions
- Exceptions
- Bitmap functions
- Complex flow control
- Global and local variables
- User Defined Function recursion

To use this sample, simply copy and paste it into a new script and save it.

[ Back to Samples ]

DynamicWindow
# This sample script uses some built-in Phantom functions to
# create some user defined functions useful for automating
# very structurally dynamic windows such as Internet Explorer.
#
# It contains a function 'FindChild' that recursively searches
# all child windows of a window to find one that matches a
# specific tag and class.
#
# It also contains 'BuildWindow' that builds a window structure
# containing all child windows of a parent window, similar
# to loading a declarations file.  However, this creates the
# entire hierarchy at runtime.
############################################################

bool DoDiagnostics = false;     # Global Diagnostics flag

############################################################
# This function is used to print diagnostics, if enabled.
function void ddisp(string s){
  if(DoDiagnostics){ disp(s); }
}

############################################################
# This function finds a child window with a specified tag
# and class.  This will search *all* children, not just
# direct children.
function window FindChild(window Parent, string Tag, string Class){
  window Child = Parent.GetChild();     # Retrieve the first child
  while(Child){                         # Cycle throug children
    ddisp("Tag: " + Child.Tag);         # Diagnostic displays
    ddisp("Class: " + Child.Class);
    if(Child.Tag == Tag){               # Check to see if tag and
      if(Child.Class == Class){         # class match...
        return Child;                   # return if so.
      }
    }
    # The tag and class do not match, check if a child of this
    # child matches (recursion)
    window Temp = FindChild(Child, Tag, Class);
    if(Temp){                           # If a match is found...
      return Temp;                      # return it.
    }
    Child = Child.GetNextSibling();     # Get the next child
  }
  return Child;                         # Return a 'null' window
}

############################################################
# This function creates a Name from a tag that is an
# acceptable Phantom variable name
function string CreateAcceptableName(string In){
  # Initialize unallowable tokens
  string Tokens = " \n\r\t+-=*/!~`\"':;.?<>,[]{}()&^%$#@|\\";
  int tlen = GetLength(Tokens);
  
  # Cycle through tokens
  for(int i = 0; i < tlen; i++){
    # Extract the token
    string T = substring(Tokens, i, i);
    # Replace all occurences of token with '_'
    In = replace(In, T, "_");
  }
  return In;
}

############################################################
# This function creates a valid Phantom variable name from
# the tag and class information of a window
function string NameFromInfo(window W){
  string sTag = W.Tag;                  # Extract the window Tag
  string sClass = W.Class;              # Extract the window Class
  
  # Trim trailing and leading whitespaces off tag and class
  sTag = trim(sTag);
  sClass = trim(sClass);
  
  # If the tag is not empty, create a Name based on the
  # tag.  Else create the name from the class.
  if(GetLength(sTag) > 0){
    sTag = CreateAcceptableName(sTag);
  }else{
    sTag = CreateAcceptableName(sClass);
  }
  
  # If a Name (held in sTag) was created and is not
  # empty, return it.
  if(GetLength(sTag) <= 0){
    # Create an exception if a valid name was not created.
    exception e;
    e.SetError("Invalid Tag: " + W.Tag);
    e.throw();
  }
  return sTag;
}

############################################################
# This function 'builds' a window hierarchy.  This can be
# used to generate a window and all children solely from
# the parent window, similar to loading a window declaration.
# This can be useful for windows that are *very* dynamic,
# whereby it is not effective to record window declarations.
function window BuildWindow(window Parent){
  window Child = Parent.GetChild();               # Get the first child
  while(Child){                                   # Cycle through children
    # Print diagnostics
    ddisp("Tag: " + Child.Tag);
    ddisp("Class: " + Child.Class);
    
    string Name = NameFromInfo(Child);            # Create a valid name
    ddisp("Name: " + Name);

    # Recursively build all children of this window
    window LocChild = BuildWindow(Child);

    # This next section tries to add the child to the
    # parent window, thereby 'building' the window set.  If
    # the child's Name already exists in the parent, an
    # exception will be generated.  Catch the exception and
    # add a number to the end of the Name.
    string LocName = Name;                       # Temporary Name variable
    int ierr = 0;                                # Exception counter
    bool bGo = true;                             # Flag to continue
    while(ierr < 10 && bGo){                     # Try up to 10 times
      try{
        Parent.AddChild(LocChild, LocName);      # Add the child to build the window
        ddisp("Child '" + LocName + "' Added");
        bGo = false;                             # No exception occured, so stop loop
      }catch(exception e){
        # Child could not be added, so increment number and append it to name
        ierr++;                                  
        LocName = Name + string(ierr);
      }
    }    
    Child = Child.GetNextSibling();              # Get the next child
  }
  return Parent;                                 # Return the newly built window
}

############################################################################
# Main Script
############################################################################

# Start Internet Explorer with Google
System("C:\\Program Files\\Internet Explorer\\iexplore.exe  www.google.com");

# Get the main internet explorer window
window Google = MainWin("Google*", "*");

# Wait up to 10 seconds for Internet Explorer to appear
WaitForWindow(Google, 10);
# Sleep 2 more to ensure it is rendered
Sleep(2);

# Build the Google window.  This adds all child windows as members
# of the 'Google' window.
disp("Building the Google Internet Explorer Window (may take time)");
Google = BuildWindow(Google);

# List the members of the Google window
ListWindow(Google);

# To illustrate that the window was built, the following accesses child windows
# just as though they came from a declarations file.  In this case, the address
# bar text is retrieved.  (NOTE: This may have to be modified based on your
# version of Internet Explorer.  Look at the output from the 'ListWindow'
# command above.)
disp("Current Address is: ");
disp(Google.Navigation_Bar.ReBarWindow32.Address_Band_Root.ComboBoxEx32.GetText());

# Find the 'Internet Explorer_Server' child, which renders the webpage.
# The previous 'BuildWindow' is not required for this, only the
# 'MainWin' call above.
disp("Finding the Internet Explorer Display");
window PageViewer = FindChild(Google, "", "Internet Explorer_Server");
disp(PageViewer);

# Set the webpage to be active
PageViewer.SetActive();
# Sleep to ensure page renders
Sleep(2);                      

# Capture am image of the page and save it.
bitmap b = PageViewer.CaptureBitmap();
b.Save("Test.bmp");

Copyright © 2000-2009 Phantom Automated Solutions, Inc.
[ Home ] [ Contact ] [ Privacy Policy ] [System Requirements]