Win32::ActAcc - `Active Accessibility' for task automation, GUI testing
Win32::ActAcc gives Perl scripts free run of the Active Accessibility client API; IAccessible; and ``WinEvents''.
Active Accessibility lets Perl scripts see what's on the screen, even when programs use ``custom controls'', lightweight (drawn) controls that are not technically windows, and the like: VB for example.
You'll want to additionally use Win32::GuiTest, and other Win32 modules, if you want your script to click, type, manipulate the clipboard, etc.
use Win32::OLE; use Win32::ActAcc; Win32::OLE->Initialize();
# Start navigating window tree at its root -- the Desktop. $accObj = Desktop(); @childAccObjs = $accObj->AccessibleChildren();
$name = $accObj->get_accName(); $rolename = Win32::ActAcc::GetRoleText($accObj->get_accRole());
Win32::ActAcc broadly parallels the Active Accessibility spec.
This pod doesn't duplicate the Active Accessibility spec. See SEE ALSO.
Note to folks already acquainted with Active Accessibility: If you've programmed with Active Accessibility in C, you know first-hand that Active Accessibility was designed with the convenience of the server programmer in mind, and little regard for the happiness of the client. Clients often need not one, but two handles to refer to an accessible GUI feature - an IAccessible* and a ``child ID''. Win32::ActAcc wraps that pair of handles in a single Perl object representing each accessible GUI feature: Win32::AO, for Accessible Object.
This manual makes the following notational innovations:
aaDigger.pl shows how to traverse the tree of accessible objects.
aaEvents.pl shows you the WinEvents that reflect what you're doing with the GUI.
aaWhereAmI.pl shows how to link a pixel location with its accessible object.
eg/aaAIMEliza.pl, at the risk of getting ridiculous, shows how to make Chatbot::Eliza respond to your incoming AOL Instant Messages. AIM is an application whose GUI is not made of standard controls, so this is an example of something you could not do (without constantly doing a File-Save As) with tools based on the Win32 API, window-classes and window-messages.
See under Tools for more about aaDigger, aaEvents, and aaWhereAmI.
The client API exposes jumping-off points like Desktop and AccessibleObjectFromWindow, and ``helper functions'' like GetRoleText.
If this is your first reading, you may want to read about Desktop and AccessibleObjectFromWindow in this section, then skip to Win32::ActAcc::AO.
Obtain an ``accessible object'' representing the desktop, so you can call the object's Active Accessibility methods:
$accObj = Desktop(); die unless 'Win32::ActAcc::AO' eq ref($accObj);
The Desktop is a natural starting-point for traversing the tree of Accessible Objects.
Once you've got an accessible object, see Win32::ActAcc::AO on how to use it.
If you do not have a clear picture in mind of the accessible-object ``tree'' of which Desktop is the root, go try out the aaDigger.pl tool.
If you have an HWND, you can convert it to an Accessible Object with AccessibleObjectFromWindow:
$accObj = AccessibleObjectFromWindow($hwnd); die unless 'Win32::ActAcc::AO' eq ref($accObj);
AccessibleObjectFromWindow's optional second parameter defaults to OBJID_WINDOW. Win32::ActAcc defines all the OBJID constants for Perl. (They come from WinAble.h.) See OBJID constants.
AccessibleObjectFromPoint checks the screen at the specified point and returns an accessible object representing the interactive item at that location.
my $accObj = AccessibleObjectFromPoint($x, $y);
Speaking of ($x, $y), how do you figure out where the mouse is? You can subscribe to the WinEvents stream and watch for mouse location-change events. See sample aaEvents.pl to see how this works.
Not all ``accessible'' objects are in the Desktop-rooted hierarchy. Therefore, AccessibleObjectFromPoint may be the only way to access some ``accessible'' objects.
Win32::ActAcc::click($xpix, $ypix, \$eh);
click()
``clicks'' somewhere on the screen, but first, it
activates the optional event monitor, so you can capture the consequences
of the click. See activate and menuPick.
You should use Win32::GuiTest for any extensive GUI manipulation. Win32::ActAcc's ``click'' method is not as flexible.
Returns localized name of a role-number.
my $chRole = Win32::ActAcc::GetRoleText($accObj->get_accRole());
Returns localized name of a state-number.
my $statebit = Win32::ActAcc::STATE_SYSTEM_FOCUSED(); my $statename = Win32::ActAcc::GetStateText($statebit);
Active Accessibility weirdness note: States are combinations of state-bits such as STATE_SYSTEM_FOCUSED (see STATE constants). GetStateText returns the name of only one of the bits that are set in the argument. If you want a quick way to get the whole truth about all the bits that are set, call GetStateTextComposite instead.
Returns a localized string of state texts, representing all of the turned-on state bits in the argument.
$stateDesc = Win32::ActAcc::GetStateTextComposite( $accObj->get_accState() );
Returns the C constant name for a state-bit defined in OleAcc.h (see STATE constants).
Returns the C constant name for an object ID defined in OleAcc.h.
nav finds a child Accessible Object by following a path from a starting point. The path specifies the name and/or role of each object along the path.
You can use nav to find the Start button. Giving undef as the starting point makes nav begin with the Desktop.
$btnStart = Win32::ActAcc::nav(Desktop(), [ "{window}", "{window}Start", "{push button}Start" ] );
nav is also useful finding a control on a dialog:
$accObjOk = Win32::ActAcc::nav($accObjDlg, [ "OK" ]);
menuPick traverses a menu (starting with a menu bar), making a list of choices. Each choice is a regexp that must match one menu item. Right before making the final choice, menuPick activates your event monitor, so you can catch the consequences of the menu choice.
my $menubar = ... my $ehDlg = Win32::ActAcc::createEventMonitor(0); menuPick($menubar, +[ qr/Format/, qr/Font/ ], \$ehDlg); $ehDlg->waitForEvent( +{ 'event'=>Win32::ActAcc::EVENT_SYSTEM_DIALOGSTART() });
(Note: menuPick is still experimental. It works with Notepad.)
Use Win32::ActAcc constants as though they were functions:
die unless (0 == Win32::ActAcc::CHILDID_SELF());
Win32::ActAcc provides the following Active Accessibility constants in addition to CHILDID_SELF and CCHILDREN_FRAME:
EVENT_SYSTEM_SOUND, EVENT_SYSTEM_ALERT, EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MENUSTART, EVENT_SYSTEM_MENUEND, EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPEND, EVENT_SYSTEM_CAPTURESTART, EVENT_SYSTEM_CAPTUREEND, EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, EVENT_SYSTEM_CONTEXTHELPSTART, EVENT_SYSTEM_CONTEXTHELPEND, EVENT_SYSTEM_DRAGDROPSTART, EVENT_SYSTEM_DRAGDROPEND, EVENT_SYSTEM_DIALOGSTART, EVENT_SYSTEM_DIALOGEND, EVENT_SYSTEM_SCROLLINGSTART, EVENT_SYSTEM_SCROLLINGEND, EVENT_SYSTEM_SWITCHSTART, EVENT_SYSTEM_SWITCHEND, EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MINIMIZEEND, EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, EVENT_OBJECT_REORDER, EVENT_OBJECT_FOCUS, EVENT_OBJECT_SELECTION, EVENT_OBJECT_SELECTIONADD, EVENT_OBJECT_SELECTIONREMOVE, EVENT_OBJECT_SELECTIONWITHIN, EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_DESCRIPTIONCHANGE, EVENT_OBJECT_VALUECHANGE, EVENT_OBJECT_PARENTCHANGE, EVENT_OBJECT_HELPCHANGE, EVENT_OBJECT_DEFACTIONCHANGE, EVENT_OBJECT_ACCELERATORCHANGE
OBJID_WINDOW, OBJID_SYSMENU, OBJID_TITLEBAR, OBJID_MENU, OBJID_CLIENT, OBJID_VSCROLL, OBJID_HSCROLL, OBJID_SIZEGRIP, OBJID_CARET, OBJID_CURSOR, OBJID_ALERT, OBJID_SOUND
STATE_SYSTEM_NORMAL, STATE_SYSTEM_UNAVAILABLE, STATE_SYSTEM_SELECTED, STATE_SYSTEM_FOCUSED, STATE_SYSTEM_PRESSED, STATE_SYSTEM_CHECKED, STATE_SYSTEM_MIXED, STATE_SYSTEM_INDETERMINATE, STATE_SYSTEM_READONLY, STATE_SYSTEM_HOTTRACKED, STATE_SYSTEM_DEFAULT, STATE_SYSTEM_EXPANDED, STATE_SYSTEM_COLLAPSED, STATE_SYSTEM_BUSY, STATE_SYSTEM_FLOATING, STATE_SYSTEM_MARQUEED, STATE_SYSTEM_ANIMATED, STATE_SYSTEM_INVISIBLE, STATE_SYSTEM_OFFSCREEN, STATE_SYSTEM_SIZEABLE, STATE_SYSTEM_MOVEABLE, STATE_SYSTEM_SELFVOICING, STATE_SYSTEM_FOCUSABLE, STATE_SYSTEM_SELECTABLE, STATE_SYSTEM_LINKED, STATE_SYSTEM_TRAVERSED, STATE_SYSTEM_MULTISELECTABLE, STATE_SYSTEM_EXTSELECTABLE, STATE_SYSTEM_ALERT_LOW, STATE_SYSTEM_ALERT_MEDIUM, STATE_SYSTEM_ALERT_HIGH, STATE_SYSTEM_PROTECTED, STATE_SYSTEM_VALID
ROLE_SYSTEM_TITLEBAR, ROLE_SYSTEM_MENUBAR, ROLE_SYSTEM_SCROLLBAR, ROLE_SYSTEM_GRIP, ROLE_SYSTEM_SOUND, ROLE_SYSTEM_CURSOR, ROLE_SYSTEM_CARET, ROLE_SYSTEM_ALERT, ROLE_SYSTEM_WINDOW, ROLE_SYSTEM_CLIENT, ROLE_SYSTEM_MENUPOPUP, ROLE_SYSTEM_MENUITEM, ROLE_SYSTEM_TOOLTIP, ROLE_SYSTEM_APPLICATION, ROLE_SYSTEM_DOCUMENT, ROLE_SYSTEM_PANE, ROLE_SYSTEM_CHART, ROLE_SYSTEM_DIALOG, ROLE_SYSTEM_BORDER, ROLE_SYSTEM_GROUPING, ROLE_SYSTEM_SEPARATOR, ROLE_SYSTEM_TOOLBAR, ROLE_SYSTEM_STATUSBAR, ROLE_SYSTEM_TABLE, ROLE_SYSTEM_COLUMNHEADER, ROLE_SYSTEM_ROWHEADER, ROLE_SYSTEM_COLUMN, ROLE_SYSTEM_ROW, ROLE_SYSTEM_CELL, ROLE_SYSTEM_LINK, ROLE_SYSTEM_HELPBALLOON, ROLE_SYSTEM_CHARACTER, ROLE_SYSTEM_LIST, ROLE_SYSTEM_LISTITEM, ROLE_SYSTEM_OUTLINE, ROLE_SYSTEM_OUTLINEITEM, ROLE_SYSTEM_PAGETAB, ROLE_SYSTEM_PROPERTYPAGE, ROLE_SYSTEM_INDICATOR, ROLE_SYSTEM_GRAPHIC, ROLE_SYSTEM_STATICTEXT, ROLE_SYSTEM_TEXT, ROLE_SYSTEM_PUSHBUTTON, ROLE_SYSTEM_CHECKBUTTON, ROLE_SYSTEM_RADIOBUTTON, ROLE_SYSTEM_COMBOBOX, ROLE_SYSTEM_DROPLIST, ROLE_SYSTEM_PROGRESSBAR, ROLE_SYSTEM_DIAL, ROLE_SYSTEM_HOTKEYFIELD, ROLE_SYSTEM_SLIDER, ROLE_SYSTEM_SPINBUTTON, ROLE_SYSTEM_DIAGRAM, ROLE_SYSTEM_ANIMATION, ROLE_SYSTEM_EQUATION, ROLE_SYSTEM_BUTTONDROPDOWN, ROLE_SYSTEM_BUTTONMENU, ROLE_SYSTEM_BUTTONDROPDOWNGRID, ROLE_SYSTEM_WHITESPACE, ROLE_SYSTEM_PAGETABLIST, ROLE_SYSTEM_CLOCK
SELFLAG_NONE, SELFLAG_TAKEFOCUS, SELFLAG_TAKESELECTION, SELFLAG_EXTENDSELECTION, SELFLAG_ADDSELECTION, SELFLAG_REMOVESELECTION, SELFLAG_VALID
NAVDIR_MIN, NAVDIR_UP, NAVDIR_DOWN, NAVDIR_LEFT, NAVDIR_RIGHT, NAVDIR_NEXT, NAVDIR_PREVIOUS, NAVDIR_FIRSTCHILD, NAVDIR_LASTCHILD, NAVDIR_MAX
IAccessible methods are in the Win32::ActAcc::AO package, so you can use them the object-oriented way.
AO's that map to HWNDs can be compared by getting their HWNDs and comparing those. Since AO's without HWNDs cannot be compared, you will want to avoid planning algorithms that depend on comparing accessible objects.
$h1 = $ao1->WindowFromAccessibleObject(); $h2 = $ao2->WindowFromAccessibleObject(); if ($h1 == $h2) { ... }
You generally can't compare two AO objects directly because of the following weirdness.
Active Accessibility weirdness note: The default Active Accessibility server helper built into Windows to represent standard controls returns a new object in response to any query. If an Active Accessibility client requests the same accessible GUI feature several times, it gets several different IAccessible* pointers back.
Win32::ActAcc always uses the same Perl object for any given IAccessible-and-childID pair, so if you have a stable server (which you probably don't), you can take advantage in Perl.
Produces human-readible (appropriate for debugging) description of an AO. Here's an example, with the fields labeled.
window:emacs: ActAcc.pod {sizeable+moveable+focusable,(4,44,1009,663),id=0,000402e2} ^ ^--title/text ^-- 'state' bits ^ ^--ID | | ^-- HWND +-role +-(left,top,width,height)
describe()
isn't supposed to die. If something goes wrong, it returns an
incomplete or empty string.
print $accObj->describe();
If your script displays the results of describe()
to its user, you
might also want to print out describe_meta()
at least once. It names
the fields.
print Win32::ActAcc::AO::describe_meta();
Reverses AccessibleObjectFromWindow:
$hwnd = $accObj->WindowFromAccessibleObject();
If no HWND corresponds to the object, WindowFromAccessibleObject dies, so you might want to run it inside an eval().
Returns the 'name' property of the accessible object. For editable text and combo box objects, it appears this is the label Windows supposes the object has: it is usually identical to the text of the immediately-preceding text object. For windows, this is the title. For client areas, this is the same as the title of the enclosing window.
$name = $accObj->get_accName();
Returns undef if the object doesn't have this property.
$role = $accObj->get_accRole();
Returns a number, probably one of the Active Accessibility ROLE_ constants (see ROLE Constants). You can convert the number to a string with Win32::ActAcc::GetRoleText. Returns undef if the object doesn't have this property.
@ch = $accObj->AccessibleChildren();
Returns a list of the accessible objects that are children of $accObj. By default it omits the invisible children: the no-argument form of AccessibleChildren is short for
@ch = $accObj->AccessibleChildren(Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 0);
The first parameter is a bit mask with 1's for the bits that matter as criteria, and the second parameter is the bit values to find in each of the '1' positions in the mask.
To find only the invisible children, you can use:
@ch = $accObj->AccessibleChildren( Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), Win32::ActAcc::STATE_SYSTEM_INVISIBLE());
which means that the INVISIBLE bit should be included in the comparison, and it must be 1. See STATE constants.
Active Accessibility weirdness note: You will probably want to use AccessibleChildren()
instead of
get_accChildCount()
and get_accChild(). AccessibleChildren probably calls those
and then improves the results. But, AccessibleChildren frequently returns fewer
children than get_accChildCount says it should.
Active Accessibility weirdness note: Some objects report 1 child with AccessibleChildren, yet accNavigate reveals more children. You can work around this problem by calling NavigableChildren instead. Note that NavigableChildren may have its own drawbacks.
In the Active Accessibility SDK, AccessibleChildren()
is part of
the API, not part of IAccessible.
Similar to AccessibleChildren, but uses accNavigate instead. Rule of thumb: Use AccessibleChildren unless it obviously is missing the children; in that case try NavigableChildren.
my @ch = $menu->NavigableChildren();
$p = $accObj->get_accParent();
Returns the parent object. Returns undef if the object has no parent.
$state = $accObj->get_accState();
Returns a number composed of bits defined by the Active Accessibility STATE_ constants (STATE_SYSTEM_NORMAL, etc.). See GetStateText and <``GetStateTextComposite''>.
Returns undef if the object doesn't have this property.
Returns the 'value' of the accessible object: the stuff in an editable text control, the outline-level of an outline item, etc.
$value = $accObj->get_accValue();
Returns undef if the object doesn't have this property.
my ($left, $top, $width, $height) = $accObj->accLocation();
Returns the accessible object's location on the screen, in pixels. (0,0) is at the top left. Dies if the object doesn't have this property.
my $smch = $accObj->accNavigate(Win32::ActAcc::NAVDIR_FIRSTCHILD()); while (defined($smch)) { my $n = $smch->get_accName(); print STDERR "$n\n"; $smch = $smch->accNavigate(Win32::ActAcc::NAVDIR_NEXT()); }
Returns an Accessible Object representing one of the base object's relations. Win32::ActAcc defines the family of NAVDIR constants from OleAcc.h. See NAVDIR constants.
accNavigate does not move focus, nor perform any other action on behalf of the user.
$desc = $accObj->get_accDescription();
Returns undef if the object doesn't have this property. If you're trying to debug your script, describe is probably more appropriate, since it appears most accessible objects don't define their description.
$help = $accObj->get_accHelp();
Returns undef if the object doesn't have this property.
$da = $accObj->get_accDefaultAction();
Returns undef if the object doesn't have this property.
$ks = $accObj->get_accKeyboardShortcut();
Returns undef if the object doesn't have this property.
$nch = $accObj->get_accChildCount();
See AccessibleChildren.
$ch = $accObj->get_accChild(3);
See AccessibleChildren.
$f = $accObj->get_accFocus();
$accObj->accDoDefaultAction();
Active Accessibility weirdness note: Sometimes doesn't do anything.
$plusOrDot = (Win32::ActAcc::CHILDID_SELF() == $ch[$i]->get_itemID()) ? '+' : '.';
get_itemID()
returns the item-ID that is part of the identity of the
accessible object.
$accObj->accSelect(Win32::ActAcc::SELFLAG_TAKEFOCUS());
See SELFLAG constants.
$accObj->click(\$eh);
click()
``clicks'' the center of the accessible object, but first, it
activates the optional event monitor, so you can capture the consequences
of the click. See activate and menuPick.
Applies a code-ref or regexp to each child, grand-child, etc. In scalar context, returns the first Accessible Object for which the code-ref returns a true value, or for which the regexp indicates a match. In array context, returns a list of all matching Accessible Objects.
$btnClose = $wNotepadApp->findDescendant( sub{ my $n = $_->get_accName(); (defined($n) && $n eq "Close") && ($_->get_accRole() == Win32::ActAcc::ROLE_SYSTEM_PUSHBUTTON()) });
$accObj->Release();
Accessible objects are COM objects, so each one must be Released when you're done with it. Perl's garbage collector and Win32::ActAcc::AO conspire to automatically Release the accessible objects, so you should not need to call Release in your scripts.
WinEvents allow a script to keep apprised of windows appearing, disappearing, moving around, and so forth; and thereby to react to the consequences of an action.
For example, the script can press Start and then, by watching the event stream, latch onto the menu that comes up.
To watch the event stream, call createEventMonitor()
and then use the
EventMonitor's waitForEvent()
or getEvent()
method. Refer to the aaEvents sample.
See also Event Details.
my $ehDlg = createEventMonitor(1);
createEventMonitor creates a Win32::ActAcc::EventMonitor object,
which the script can poll for WinEvents using waitForEvent()
or getEvent().
The ``1'' means the EventMonitor is immediately activated. Otherwise the EventMonitor is latent until activated, which typically happens in one of two ways:
Here are the methods on the EventMonitor object you get from createEventMonitor.
Sometimes, you want to see whether something happens. Other times, you know
what will happen, but you want to find out which Accessible Object it happens to.
waitForEvent()
meets both needs.
Here's a sample of how to wait (for up to 30 seconds) for a Notepad window to appear.
$aoNotepad = $eh->waitForEvent( +{ 'event'=>Win32::ActAcc::EVENT_OBJECT_SHOW(), 'name'=>qr/Notepad/, 'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW() }, 30);
waitForEvent blocks the script until a matching event arrives, or the timeout expires. The return value is the accessible object of the winning event, or undef if the timeout expired. So: You see how the sample cunningly not only learns that a Notepad windows has appeared, but actually gets its Accessible Object for later use (such as to close the window).
You can omit the timeout, in which case waitForEvent waits for a matching event, which might mean waiting a very long time indeed.
The hash's entries are:
If your desires don't fit the hash mold, you can give a code-reference instead. waitForEvent returns when the code returns any non-undef. waitForEvent returns what the code returned.
$eh->waitForEvent(sub{print Win32::ActAcc::Event::evDescribe(@_)."\n";undef}, $secs);
You will usually want to use waitForEvent. But, just in case, there is a way to retrieve one event at a time.
getEvent retrieves an event from the event monitor, or undef if no event is ready.
The event is a blessed hash (Win32::ActAcc::Event).
$eh->clear();
Erases the backlog of events on the event monitor.
synch()
lets you bookmark an EventMonitor and return later to the bookmarked point.
$eh1->synch($eh2);
``Synchronizes'' $eh1 with $eh2 by setting $eh1's event-buffer cursor to $eh2's,
so that $eh1->getEvent()
will
return the same event as $eh2->getEvent(). synch()
can move the monitor forward or backward;
in other words, it can both advance and rewind. (But, when rewinding, watch out for
buffer overrun. The spot you rewind to, may have been re-used since the time the event
was written that you think you are rewinding to.)
$a = $eh->isActive();
Returns a true value if the event monitor is active, a false value if it is latent.
$eh->activate(1); # activate $eh->activate(0); # deactivate
Activating a monitor makes it ``catch up'' with all events received so far, and makes it sensitive to future events. Activating an already-active monitor has no effect on it.
Deactivating a monitor makes it useless, until it is reactivated.
my $ec = $eh->getEventCount();
Returns a cumulative total number of events caught by the event hook installed by Win32::ActAcc. (All EventMonitor objects feed from this same event hook.)
This debug function displays the EventMonitor's events for a certain number of seconds.
$eh->debug_spin(60);
An event is an object of type Win32::ActAcc::Event. It's a hash with fields as described in the API documentation:
event hwnd idObject idChild dwmsEventTime
$e = $eh->getEvent(); print $$e{'event'} . "\n";
``Event'' is a constant (see EVENT Constants). You can test it like this:
next unless Win32::ActAcc::EVENT_OBJECT_VALUECHANGE()==$$e{'event'};
$accObj = $e->getAO();
Returns the accessible object that the event pertains to.
Active Accessibility weirdness note: getAO sometimes dies with an access-violation error. You may want to put your calls to getAO into an eval.
print $e->evDescribe() . "\n";
Good for debugging - returns some information about the event.
Returns the C constant name for a WinEvent number defined in WinAble.h. See EVENT Constants.
Obtain an ``accessible object'' from information in a WinEvent. (You may prefer to use the object-oriented $e->getAO() way instead.)
my $accObj = AccessibleObjectFromEvent($$e{'hwnd'}, $$e{'idObject'}, $$e{'idChild'});
Each Perl process with an active EventMonitor installs an Active Accessibility ``in-proc'' event hook that records all events in a fixed-size circular buffer.
All of the script's EventMonitor objects cursor through the process' lone circular buffer.
You will want to tightly bracket the scope of your EventMonitor objects (or deactivate them as soon as they are no longer interesting) since the event hook slows down your computer slightly and it's a pity to leave an event hook going when you don't need it.
There's no overrun indicator on the circular buffer, so try to keep your EventMonitors reasonably up-to-date lest you miss an event.
EventMonitors don't seem to pick up any WinEvents from Command Prompt windows in Windows 2000. Perhaps these windows are owned by a process that resists in-proc event hooks. Hmm.
Circular buffer size (in events) for this build of ActAcc:
5000
aaDigger lets you navigate the hierarchy of accessible objects, rooted at the Desktop window. aaDigger has its own manpage.
When you're planning an Active Accessibility script, aaDigger helps you get your feet on the ground.
aaEvents makes a continuous display of your system's WinEvents. When you're casting about for clues about which event your script should be keying to a real-world occurrence, aaEvents can help you make up your mind.
aaWhereAmI continuously describes the accessible object under the cursor at any given moment.
Active Accessibility weirdness note: Not all accessible objects have a place in the hierarchy that has Desktop at its root.
You can't use an ``accessible object'' with Win32::OLE. Especially with Microsoft Office, it would be nice to get a ``native object model'' IDispatch* from AccessibleObjectFromWindow, and hand it off to Win32::OLE to make Office-specific OLE Automation method calls.
There's no overrun indicator on an EventMonitor. You can't tell it to ignore mouse-move events - not even redundant or superseded ones.
Win32::ActAcc probably doesn't work multi-threaded.
nav()
and findDescendant()
should accept the same path arguments.
And the path notation should provide a dizzying combination of XPath and
regular-expression features. (For XPath, see http://www.w3.org/TR/xpath.)
EventMonitors install only in-proc hooks. Maybe that's why they don't pick up any events from Command Prompt windows.
Win32::ActAcc doesn't do Unicode. If you run aaDigger.pl and point it to the Russian version of Windows Media Player, the text all comes back as question marks.
perl makefile.pl nmake nmake install nmake test
Yes, you have to install it before you test it. Otherwise it can't find its DLL. Probably someone will figure out how to fix this.
Prerequisites:
ActivePerl users can install Win32::ActAcc using PPM.
ppm install --location=. Win32-ActAcc
To check the installation, you may try aaDigger.pl. The test suite (nmake test) doesn't seem to work if you do the ppm installation.
Copyright 2001, Phill Wolf.
You may use Win32::ActAcc under the terms of the Artistic License, as specified in the README file of the Perl distribution.
Phill Wolf, pbwolf@cpan.org
Active Accessibility documentation. As of this writing, it is available on http://msdn.microsoft.com on the ``Libraries'' page:
Platform SDK User Interface Services Accessibility Microsoft Active Accessibility
Win32::OLE
Win32::GuiTest