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");
| |