# Copyright 2001, Phill Wolf.  See README.

# Win32::ActAcc (Active Accessibility) documentation

=head1 NAME

Win32::ActAcc - `Active Accessibility' for task automation, GUI testing

=head1 SYNOPSIS

=over 4

=item *

Active Accessibility client API

 use Win32::OLE;
 use Win32::ActAcc;
 Win32::OLE->Initialize();
 $ao = AccessibleObjectFromPoint(320,240);
 @children = $ao->AccessibleChildren();
 $hwnd = $ao->WindowFromAccessibleObject();
 $ao2 = AccessibleObjectFromWindow($hwnd);

=item *

IAccessible

 print $ao->get_accName() . "\n";
 print $ao->get_accValue() . "\n";
 print $ao->get_accDefaultAction() . "\n";
 $statebits = $ao->get_accState();
 $rolenum = $ao->get_accRole();
 $ch1 = $ao->accNavigate(NAVDIR_FIRSTCHILD());
 $p = $ao->get_accParent();

=item *

WinEvents

 $aoNotepad = Win32::ActAcc::waitForEvent(
    +{ 'event'=>EVENT_OBJECT_SHOW(),
       'name'=>qr/Notepad/,
       'role'=>ROLE_SYSTEM_WINDOW()});

=item *

Iterators

Win32::ActAcc's iterators can drill into menus and outlines, in addition to 
the Active Accessibility object hierarchy. 

 # display children of $ao
 my $iter = $ao->iterator();
 $iter->open();
 my $aoi;
 while ($aoi = $iter->nextAO())
 {
     print $aoi->describe() . "\n";
 }
 $iter->close();

=item *

Finding accessible objects

 # find any descendant
 $notepadTextArea = $aoNotepad->drill("{editable text}", +{'max'=>1, 'min'=>1});

 # find immediate child
 $AimConversation = $aoIM->dig( +[ +{'role'=>ROLE_SYSTEM_WINDOW(), 'name'=>qr/\<HTML\>/ } ] );

 # follow path
 $tray = Win32::ActAcc::Desktop()->dig([ 
            +{'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW(), 'name'=>'', 'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}}, 
            +{'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW(), 'name'=>'', 'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}}, 
            +{'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW(), 'name'=>'', 'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}}, 
            +{'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW(), 'name'=>'Tray', 'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}}, 
            +{'role'=>Win32::ActAcc::ROLE_SYSTEM_PAGETABLIST(), 'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}} ], 
        +{'max'=>1,'min'=>1} );

=item *

Task-automation conveniences

 use Win32::OLE;
 use Win32::ActAcc;
 use Win32::ActAcc::Shell2000;
 #
 Win32::OLE->Initialize();
 $menu = Win32::ActAcc::Shell2000::StartButtonMenu();
 Win32::ActAcc::clearEvents();
 $menu->menuPick([ qr/^Programs/, qr/Accessories/i, qr/Notepad/i ]);
 $aoNotepad = Win32::ActAcc::waitForEvent(
    +{ 'event'=>EVENT_OBJECT_SHOW(),
       'name'=>qr/Notepad/,
       'role'=>ROLE_SYSTEM_WINDOW()});
 $aoNotepad->menuPick(+["File", "Exit"]);

=item *

Tools and samples

=over 4

=item *

B<aaDigger.pl> shows how to traverse the tree of accessible objects.

=item *

B<aaEvents.pl> shows you the WinEvents that reflect what you're doing with the GUI.

=item *

B<aaWhereAmI.pl> shows how to link a pixel location with its accessible object.

=item *

B<elizaNotepad.pl>, just for fun, uses Notepad as the user interface to Chatbot::Eliza.

=back 4

See under L<"Tools"> for more about aaDigger, aaEvents, and aaWhereAmI. 

=back 4

You'll want to additionally use Win32::GuiTest, and other Win32 modules,
if you want your script to click, type, manipulate the clipboard, etc.

=head1 DESCRIPTION

=head2 Active Accessibility and Win32::ActAcc

Active Accessibility is an API from Microsoft.  See L<"SEE ALSO"> for a
pointer to the documentation on Active Accessibility.  

Win32::ActAcc is based on Active Accessibility 1.3 on Windows 2000.  With other
Active Accessibility implementations, your mileage may vary.

In keeping with Perl's culture of laziness and impatience, Win32::ActAcc smoothes
out some of the bumps in Active Accessibility for Perl programmers.  For example,
a standard Active Accessibility client must carry around I<two> keys to each "accessible"
thing: an IAccessible* and a child-ID.  What a bore!  Luckily, with Win32::ActAcc, an accessible object
is an accessible object (Win32::ActAcc::AO); no pairs of keys.

Active Accessibility has three parts -- the "client API", which is not object-based; 
IAccessible, which is an API that each "accessible object" is supposed to implement; 
and WinEvents, which tell you
what's going on.

=head3 Active Accessibility client API: overview

The client API is mainly useful for getting an "accessible object" corresponding to a "real-world" on-screen object
like a window or pushbutton.
Then you can go use the accessible object using the L<"Win32::ActAcc::AO"> methods.

(The other two ways of getting an accessible object are:  asking one for another, as with L<"get_accParent">, and 
monitoring L<"WinEvents"> as windows appear, disappear, move, and so forth.)

Win32::ActAcc provides access to these Active Accessibility client API functions:
L<"AccessibleChildren">, L<"AccessibleObjectFromEvent">, L<"AccessibleObjectFromPoint">,
L<"AccessibleObjectFromWindow">, L<"GetRoleText">,
L<"GetStateText">, L<"WindowFromAccessibleObject">.

=head3 IAccessible: overview

Win32::ActAcc::AO and its subclasses provide access to these IAccessible functions:
L<"accDoDefaultAction">,
L<"accLocation">, 
L<"accNavigate">, 
L<"accSelect">, 
L<"get_accChild">, 
L<"get_accChildCount">, 
L<"get_accDefaultAction">, 
L<"get_accDescription">, 
L<"get_accFocus">, 
L<"get_accHelp">, 
L<"get_accKeyboardShortcut">, 
L<"get_accName">, 
L<"get_accParent">, 
L<"get_accRole">, 
L<"get_accState">, 
L<"get_accValue">. 

Win32::ActAcc does not yet implement get_accSelection (which does not operate on text edits anyway).

=head3 WinEvents: overview

You can wait for something to happen by using waitForEvent.  And, you can open
your own "cursor" on the stream of WinEvents, using L<"createEventMonitor">.

=head2 There's more than one way to do it

In keeping with the Perl principle of TMTOWTDI ("There's more than one way to do it"),
and the Perl culture of laziness and impatience, 
three 
innovations were necessary, extending raw Active Accessibility:

=over 4

=item *

B<Object-orientation.>  Whenever Win32::ActAcc gives you an AO, what you
get is actually a subclass specific to the
AO's role.  For example, if the role is ROLE_SYSTEM_OUTLINE, you get an object 
from package Win32::ActAcc::Outline, which inherits from AO.  
See L<"AO Subclasses">.  This allows polymorphism, which
in turn helps us write programs that do the right thing, despite themselves.
Object-orientation is a slippery slope and led to the further innovations:

=item *

B<Conveniences.>  Such as L<"menuPick"> and outline navigation:  things you
might suppose would be built-in to Active Accessibility in an obvious and straightforward way, but aren't.  

=item *

B<Iterators.>  Active Accessibility gives you three ways to enumerate the "children" of an 
accessible object.  And darned if they don't sometimes yield conflicting results!  Worse, you
can't switch freely among them:  one gives you a list, one gives you random access, 
and one requires that you step from one child to the next.  So Win32::ActAcc wraps the navigation 
techniques, and others, with iterators that all work alike.  Write your algorithm once and change iterators any time.

=back 4

Active Accessibility has some minor imperfections.  Of course, Win32::ActAcc itself also has imperfections.
To aid the reader in distinguishing the two, we have taken the liberty of calling out
some "Active Accessibility weirdnesses" as such.  All other parts of this document
describe the idiosyncracies of Win32::ActAcc.

=head2 Win32::ActAcc

If this is your first reading, you may want to read about 
Desktop and AccessibleObjectFromWindow in this section,
then skip to L<"Win32::ActAcc::AO">.

=head3 Desktop

Obtain an "accessible object" representing the desktop, so you can call the object's 
Active Accessibility methods:

 $accObj = Desktop();

The Desktop is a natural starting-point for traversing the tree of Accessible Objects.

Once you've got an accessible object, see L<"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 L<"aaDigger.pl"> tool.  

=head3 AccessibleObjectFromWindow

If you have an HWND, you can get an Accessible Object for it:

 $accObj = AccessibleObjectFromWindow($hwnd);

AccessibleObjectFromWindow's optional second parameter defaults to OBJID_WINDOW.  
See L<OBJID constants>.

=head3 AccessibleObjectFromPoint

AccessibleObjectFromPoint checks the screen at the specified point and returns
the foremost accessible object occupying 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.

=head3 click

 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 L<"activate"> and L<"menuPick">.

You should use Win32::GuiTest for any extensive GUI manipulation.  Win32::ActAcc's "click" method is not 
as flexible.

=head3 GetRoleText

Returns localized name of a role-number.

 my $chRole = Win32::ActAcc::GetRoleText($accObj->get_accRole());

=head3 GetStateText

Returns localized name of a state-number.  

 my $statebit = STATE_SYSTEM_FOCUSED();
 my $statename = Win32::ActAcc::GetStateText($statebit);

Normally, you'll want to call GetStateTextComposite instead, since GetStateText works with only one state bit.
States are I<combinations>
of state-bits such as STATE_SYSTEM_FOCUSED (see L<STATE constants>).  

=head3 GetStateTextComposite

Returns a localized string of state texts, representing all of the turned-on state
bits in the argument.  L<"describe"> uses GetStateTextComposite.

 $stateDesc = Win32::ActAcc::GetStateTextComposite( $accObj->get_accState() );

=head3 StateConstantName

 my $n = Win32::ActAcc::StateConstantName(STATE_SYSTEM_INVISIBLE());

Returns the C constant name for a state-bit defined in OleAcc.h (see L<STATE constants>).

=head3 ObjectIdConstantName

 my $objname = Win32::ActAcc::ObjectIdConstantName($$e{'idObject'});

Returns the C constant name for an object ID defined in OleAcc.h (see L<OBJID constants>).

=head3 waitForEvent (Win32::ActAcc)

Waits for an event, using the default event cursor.  See the L<"waitForEvent"> method of Win32::ActAcc::EventMonitor.

=head3 clearEvents (Win32::ActAcc)

Discards any unconsumed events on the default event cursor.  See the L<"clear"> method of Win32::ActAcc::EventMonitor.

=head2 Win32::ActAcc::AO - properties and actions

Here are the methods on an "accessible object".  This package includes the IAccessible methods, some of which have funny names.

Active Accessibility weirdness note:  There is no guarantee in Active Accessibility that 
an onscreen object shall be represented by one-and-only-one IAccessible*.  In fact,
the Active Accessibility server helper 
built into Windows to represent standard controls 
seems to generally return a new object in response to any query.  
So, there is no sure-fire way to compare Accessible Objects.

Even when an Active Accessibility server returns the same IAccessible* in response to two different calls, Win32::ActAcc may
make them into discrete Win32::ActAcc::AO objects.

=head3 describe

Produces human-readible (appropriate for debugging) description of an AO. 
It's just like what you get from the aaDigger utility.  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();

For outline items, describe() includes '>' symbols corresponding to the hierarchy depth, immediately to the left of the name.

=head3 WindowFromAccessibleObject

Reverses L<"AccessibleObjectFromWindow">:  

 $hwnd = $accObj->WindowFromAccessibleObject(); 

If no HWND corresponds to the object, WindowFromAccessibleObject dies, so you might
want to run it inside an eval().

=head3 get_accName

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.

=head3 get_accRole

 $role = $accObj->get_accRole();

Returns a number, one of the Active Accessibility ROLE_ constants
(see L<ROLE Constants>).  You can convert the number
to a string with L<"GetRoleText">.
Returns undef if the object doesn't have this property.

=head3 get_accState

 $state = $accObj->get_accState();

Returns a number composed of bits defined by the Active Accessibility STATE_ constants
(L<STATE Constants>).  See L<"GetStateTextComposite">.

Returns undef if the object doesn't have this property.

=head3 get_accValue

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.

=head3 accLocation

 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.

=head3 get_accDescription

 $desc = $accObj->get_accDescription();

Returns undef if the object doesn't have this property.
If you're trying to debug your script, L<"describe"> is probably more appropriate,
since it appears most accessible objects don't define their description.  

=head3 get_accHelp

 $help = $accObj->get_accHelp();

Returns undef if the object doesn't have this property.

=head3 get_accParent

 $p = $accObj->get_accParent();

Returns the parent object.  Returns undef if the object has no parent.

=head3 get_accDefaultAction

 $da = $accObj->get_accDefaultAction();

An object's default action may depend on the mouse location, which window is topmost, which shift/control keys are pressed, etc.
Returns undef if the object doesn't have this property.

=head3 get_accKeyboardShortcut

 $ks = $accObj->get_accKeyboardShortcut();

Returns undef if the object doesn't have this property.

=head3 get_accFocus

 $f = $accObj->get_accFocus();

=head3 accDoDefaultAction

 $accObj->accDoDefaultAction();

The effect of accDoDefaultAction is supposed to reflect L<"get_accDefaultAction">.

Win32::ActAcc calls a hook function before doing the default action.  Initially, the
hook is undef, but you can install different code if you like.  The sample
displays a record of the actions:

 $Win32::ActAcc::AO::accDoDefaultActionHook = sub 
 {
     my $ao = shift;
     print "accDoDefaultAction(".$ao->describe().")\n";
 };

=head3 get_itemID

 $plusOrDot = (CHILDID_SELF() == $ch[$i]->get_itemID()) ? '+' : '.';

get_itemID() returns the item-ID that is part of the identity of the 
accessible object.

=head3 accSelect

 $accObj->accSelect(SELFLAG_TAKEFOCUS());

See L<SELFLAG constants>.

=head3 click  (center of Accessible Object)

 $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 L<"activate"> and L<"menuPick">.

=head3 Release

 $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.

=head2 Win32::ActAcc::AO - comparison

=head3 match

Match is how 'drill' and 'dig' decide whether they've found what
you are looking for.  match checks the AO against specified criteria
and returns a true value if none of the criteria is inconsistent with
the AO's attributes.

 $b = $ao->match( CRITERIA );

CRITERIA is flexible:

 $b = $ao->match("Close"); # Is AO's name exactly Close?
 $b = $ao->match( +{'name'=>"Close"} ); # ... using a hash.
 #
 $b = $ao->match(qr/Close/); # Does AO's name match that regexp?
 $b = $ao->match( +{'name'=>qr/Close/} ); # ... using a hash.
 #
 $b = $ao->match("{ROLE_SYSTEM_PUSHBUTTON}Close"); # Is AO a pushbutton named Close?
 $b = $ao->match("{push button}Close"); # ... using localized 'role text'
 $b = $ao->match("{Pushbutton}Close"); # ... using ActAcc package name
 $b = $ao->match( +{'role'=>ROLE_SYSTEM_PUSHBUTTON(), 'name'=>"Close"} ); # ...
 $b = $ao->match( +{'rolename'=>'Pushbutton', 'name'=>"Close"} ); # ...
 #
 $b = $ao->match( sub{...} ); # Does sub($ao) return a true value?
 $b = $ao->match( +{'code'=>sub{...} } ); # ... using a hash.
 #
 # Find only visible windows.
 $b = $ao->match( +{'state'=>+{'mask'=>STATE_SYSTEM_INVISIBLE(), 'value'=>0} } ); 
 #
 # Find only INvisible windows.
 $b = $ao->match( +{'state'=>+{'mask'=>STATE_SYSTEM_INVISIBLE(), 'value'=>STATE_SYSTEM_INVISIBLE()} } ); 

So you see:  For the discriminator, you can use a string, a regexp, a code reference, 
or a hash.

Only in the "{ROLE_SYSTEM_PUSHBUTTON}Close" case can you combine a role with a name 
in one string.  (If you want to avoid that interpretation of the braces, use the hash instead.)

Hash members:

=over 4

=item *

B<rolename> - a localized 'role text' (as though received from GetRoleText), 
or an ActAcc package name with or without the Win32::ActAcc:: part,
or the name of a role constant with or without the ROLE_SYSTEM_ part.

=item *

B<role> - the value of a role constant.

=item *

B<name> - a regexp or a string (if a string, then case matters and it must match the I<entire> name).

=item *

B<state> - a hash with 'mask' and 'value' members.  match takes the state of each AO, does
a bitwise AND with the mask, then compares with the value.  

=item *

B<code> - a coderef invoked with two arguments: the subject AO (also in
$_), and the criterion.  If your code needs additional parameters or
needs to squirrel away information for the caller of match, use closures.  The code
is called only if the other criteria all match.  Return a true value
to indicate a match.

=back 4

For those frustrating occasions where you're right and the computer is wrong,
match can tell you what about the criteria is inconsistent with the AO.

 my $reasonForMismatch;
 $b = $ao->match( CRITERIA, \$reasonForMismatch );
 print $reasonForMismatch;

=head3 Equals

 my $dt = Win32::ActAcc::Desktop();
 my $e1 = $dt->Equals($dt);
 die unless $e1;

Equals returns a true value if, and only if, at least one of these conditions holds.

=over 4

=item *

the IAccessible* and ID of the two accessible objects both match.

=item *

the accessible objects both reify an HWND, and their HWNDs are equal.

=back 4

Active Accessibility weirdness note:  Because Active Accessibility servers usually return a distinct Accessible Object for each method call,
and not all Accessible Objects have an HWND, it's not wise to rely very heavily on Equals 
except under not very general circumstances.

There are other ways to guess about the "equality" of two accessible
objects.  For example, the AONavIterator class regards $a and $b equal
if $a->describe() gives the same string as $b->describe(): thereby
taking into consideration name, role, state, location, default action,
HWND, and whatnot.  Architectural note:  Yes, relying on describe() is gross.

=head2 Win32::ActAcc::AO - navigation by iterator

Iterators are devices that give you access to all or some of an Accessible Object's child-objects.  Win32::ActAcc's iterators
are implemented on top of Active Accessibility, which itself does not use the iterator concept. 

You can use an iterator with a loop:

 my $iter = $ao->iterator();
 $iter->open();
 my $aoi;
 while ($aoi = $iter->nextAO())
 {
     print $aoi->describe() . "\n";
 }
 $iter->close();

Or you can use an iterator to populate a list:

 my $iter = $ao->iterator();
 my @L = $iter->all();
 print join($_->describe(), @L) . "\n";

You can pass flags to the iterator() method if you have special needs:

 my $iter = $ao->iterator( +{'lax'=>1} ); # enumerate client's children along with client (like 'dig')
 my $iter = $ao->iterator( +{'active'=>1} ); # treat outline items and menu items hierarchically
 my $iter = $ao->iterator( +{'perfunctory'=>1} ); # use speedier AOIterator rather than AONavIterator
 my $iter = $ao->iterator( +{'nav'=>1} ); # use NavIterator rather than AONavIterator

Active iteration on outline items, menu items, and menu buttons involves "clicking" on the GUI
and could cause certain programs to take action in a way you wouldn't expect.  For example,
using active iteration on the outline in the Windows Explorer can cause Explorer to prompt 
you for the password to network resources, or to complain that there is no disk in your A: drive.
Active iteration on menus doesn't work unless the menu is on the active (topmost) window.

=for html <center>

B<Iterators>

=for html </center> 

=for html <table border=1>

=for html <tr><td>

AOIterator

=for html </td><td>

Uses L<"AccessibleChildren">

=for html </td></tr>

=for html <tr><td>

NavIterator

=for html </td><td>

Uses L<"accNavigate">(NAVDIR_FIRSTCHILD), then repeatedly accNavigate(NAVDIR_NEXT)

=for html </td></tr>

=for html <tr><td>

AONavIterator

=for html </td><td>

Combines AOIterator with NavIterator.  The point is to find even those children that one technique
or the other misses.  This is the default iterator for Win32::ActAcc::AO.
This iterator considers two AO's as equal if describe() describes them with equal strings.
This iterator is slow, but thorough.

=for html </td></tr>

=for html <tr><td>

DelveClientIterator

=for html </td><td>

Folds an AO's I<client's> children in with the AO's children (the title bar and whatnot),
in effect collapsing layers of the hierarchy that sometimes seem to get underfoot.
(Uses AONavIterator.)  This is the default iterator for Win32::ActAcc::Window.

=for html </td></tr>

=for html <tr><td>

L<"MenuIterator">

=for html </td><td>

Follows a "logical" hierarchy of menu items, just as humans perceive it.  
Default iterator for Win32::ActAcc::Menubar and Win32::ActAcc::MenuItem.

=for html </td></tr>

=for html <tr><td>

OutlineIterator

=for html </td><td>

Opens, traverses and closes outline items.  
Follows a "logical" hierarchy of outline items, just as humans perceive it.  
This is the default iterator for Win32::ActAcc::Outline
and Win32::ActAcc::OutlineItem.  (Iterating the Outline is the same as iterating its root item.)

=for html </td></tr>

=for html </table>

Each AO has a default iterator type, which you get an instance of by calling $ao->iterator(). 
But if you absolutely need a certain type of iterator, you can be explicit:

 my $oi = new Win32::ActAcc::NavIterator($ao); # choose non-default iterator

Only AOIterator, NavIterator, and AONavIterator are faithful to Active Accessibility's
notion of parent/child relationships.  The other iterators fudge.  For example, 
MenuIterator makes submenus seem to be children of menus.   OutlineIterator makes
sub-items appear to be children of items.  DelveClientIterator makes
controls that are technically in a window's client area, appear to be children of 
the window itself.

Only AOIterator and NavIterator are faithful to Active Accessibility's I<order> of
child items.  (AONavIterator comes close.)

=head3 MenuIterator

MenuIterator opens, traverses (with AONavIterator), and closes menus.

"Opening" a menu may not work unless the menu is in the topmost active window; it
seems to cause the menu to actually open on-screen, as though you'd clicked it.

Note: In Active Accessibility, standard menus work differently from
custom (Office) menus, which in turn work differently from the Start
menu.  Yuck!  But Win32::ActAcc tries to smooth over the differences,
so they all work the same from the point of view of Perl scripts.

=head2 Win32::ActAcc::AO - Hunting for children and descendants

=head3 drill

drill takes the AO as the root of a subtree of accessible objects,
applies a criterion to each object in the tree, and returns a list
of the objects that match the criterion.

 @list = $ao->drill( CRITERIA );
 @list = $ao->drill( CRITERIA, OPTIONS );

drill finds "invisible" objects as well as visible ones.  If you're 
looking for something visible, remember to specify so in the criteria:

 ... +{'role'=>Win32::ActAcc::ROLE_SYSTEM_WINDOW(), 
       'name'=>'', 
       'state'=>+{'mask'=>Win32::ActAcc::STATE_SYSTEM_INVISIBLE(), 'value'=>0}}, ...

drill prunes menu bars and outlines unless you specify a prunes list.  That is, 
drill normally doesn't examine the children of menu bars and outlines, since
they require active iteration, which could cause side effects.

 @btnClose = $wNotepadApp->drill( 
	sub{	
		my $n = $_->get_accName(); 
		(defined($n) && $n eq "Close") && 
			($_->get_accRole() == ROLE_SYSTEM_PUSHBUTTON()) 
	});

You can customize drill by specifying a hash of options.  The hash keys are:

=over 4

=item *

'min'=>I<n> -- make drill die if it doesn't find at least I<n> matches.

=item *

'max'=>I<n> -- make drill return as soon as it finds I<n> matches.  
If max is 1, then drill returns a scalar value instead of a list.

=item *

'pruneOnMatch'=>1 -- make drill not examine the children of an AO that matches.

=item *

'prunes'=>I<+[CRITERIA, CRITERIA, etc.]> -- 
make drill not examine the children of an AO that matches at least one of the criteria.
If the options hash does not have a 'prunes' key, then the default is to prune
at Menubar and Outline objects.  To probe those, you can specify 'prunes' as an empty list.

=back 4

=head3 dig

dig finds Accessible Objects by following a path from a starting point.
The path specifies the criterion to match at each step.

 @aos = $ao->dig( +[ CRITERIA, CRITERIA, etc. ] );
 @aos = $ao->dig( +[ CRITERIA, CRITERIA, etc. ], +{ OPTIONS } );

Here's one way to find the Start button.  We're telling dig to start at the desktop;
from there, find a window (by any name), within it a window called Start, and 
in turn within it a pushbutton called Start.  How did we know?!  We used aaDigger and went exploring.
Humility gets you a long way in the business of automating usage of GUIs.  

 $btnStart = Desktop()->dig([ "{window}", "{window}Start", "{push button}Start" ] );

dig lets you be somewhat imprecise (for example, the above quest for the Start button did not
specify the name of the top-level window, so dig might have to hunt through several).  dig is more
efficient, the more precise the parameters are.

dig is also useful finding a control on a dialog:

 $accObjOk = $accObjDlg->dig([ "OK" ]);

If you like, you can specify the path as an array of hashes instead of an array of strings.
Each hash must have a 'role' entry and a 'name' entry.  
The role is a string like "menu bar", which aaDigger can tell you.  
The name must be either a string or a regexp.

dig uses the default iterator of each AO, and therefore automatically traverses "client" windows without being told to.  
Windows with border ornaments typically have a title-bar, a menu-bar, and a
"client" area; the interesting stuff is within the client area.  

You can customize dig by specifying a hash of options.  The hash keys are:

=over 4

=item *

'min'=>I<n> -- make dig die if it doesn't find at least I<n> matches.

=item *

'max'=>I<n> -- make dig return as soon as it finds I<n> matches.  
If max is 1, then dig returns a scalar value instead of a list.

=item *

'trace'=1 -- make dig display information on STDERR about what it is doing.

=back 4

=head3 tree

The tree method performs a depth-first traversal of the Accessible Object hierarchy.  At each 
Accessible Object, tree() calls code that you specify.  

For example, we can display the Accessible Object hierarchy:

 $ao->tree( sub{my ($ao,$tree)=@_; print ' 'x($tree->level()).$ao->describe."\n";} );

tree() uses the default iterator for each AO it visits.  You can supply iterator flags as a
second argument to tree():

 $ao->tree( sub{print "*";}, +{'lax'=>1, 'active'=>1});

What can the "sub" do?  It gets two arguments ($ao, $tree).  The $tree argument 
gives access to the tree-context object, which has the following methods:

B<level()> returns 0 for the root (i.e., the AO whose 'tree' method was called), 1 for the root's children, 2 for the root's grandchildren, etc.

B<prune()> causes tree not to enumerate the children of $ao; to skip them and go on with $ao's siblings.

B<stop()> causes tree to return to its caller without enumerating any more accessible objects.

=head2 Win32::ActAcc::AO - navigation methods

These are methods for exploiting the parent/child relationships among Accessible Objects.
You will probably want to use the iterators instead, to get around the problems with 
accessible-object navigation in Active Accessibility -- 

=over 4

=item *

AccessibleChildren and accNavigate disagree -- they often return different results!

=item *

there is no convenient way to
get at the "logical children" of a menu or outline

=item *

AccessibleChildren returns a list, whereas accNavigate makes you loop; you can't write a single algorithm that can work with either data source.

=back 4

Win32::ActAcc fills in those gaps with I<iterator> algorithms.  The iterators
are polymorphic, so you can use them all the same way, and write your own
algorithms that can operate on any iterator. 

But, in case iterators don't suit your need, here are the more primitive alternatives.

=head3 AccessibleChildren

 @ch = $accObj->AccessibleChildren();

Returns a list of the accessible objects that are children
of $accObj.

By default, in Win32::ActAcc, AccessibleChildren omits the invisible children; that's because
the no-argument form of AccessibleChildren is short for

 @ch = $accObj->AccessibleChildren(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.  So you can
see that the default parameters indicate to find only the children whose
STATE_SYSTEM_INVISIBLE state bit holds 0.

To find the complement, i.e., I<only the invisible
children>, you can use:

 @ch = $accObj->AccessibleChildren(
    STATE_SYSTEM_INVISIBLE(), 
    STATE_SYSTEM_INVISIBLE());

which means that the INVISIBLE bit should be included in the comparison, and it must be 1.  
The second parameter is 1 shifted into the bit position for STATE_SYSTEM_INVISIBLE.
See L<STATE constants>.

To find all the children, visible or not, you can use:

 @ch = $accObj->AccessibleChildren(0,0); # no state bit matters, so all children qualify

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 using
AONavIterator or NavIterator (each of which may have its own drawbacks!).

In the Active Accessibility SDK, AccessibleChildren() is part of
the API, not part of IAccessible.

=head3 accNavigate

 my $smch = $accObj->accNavigate(NAVDIR_FIRSTCHILD());
 while (defined($smch))
 {
 	my $n = $smch->get_accName();
 	print STDERR "$n\n";
 	$smch = $smch->accNavigate(NAVDIR_NEXT());
 }

Returns an Accessible Object representing one of the base object's relations.  
See L<NAVDIR constants>.

Returns undef if asked for something that does not exist, I<provided that the server follows the spec and returns S_FALSE in that case>.

accNavigate does not move focus, nor perform any other action on behalf of the user.  

=head3 get_accChildCount

 $nch = $accObj->get_accChildCount();

See L<"AccessibleChildren">.

=head3 get_accChild

 $ch = $accObj->get_accChild(3);

See L<"AccessibleChildren">.

=head2 AO Subclasses

Perl scripts can treat accessible objects polymorphically, since Win32::ActAcc establishes
a subclass for each Role of accessible object.

This is how Menubar's iterator method works differently from Outline's; but from the caller's
perspective, they do the same thing and there is no need to distinguish them.

These packages derive from Win32::ActAcc::AO, inherit all its methods, and  
are implemented using its methods.  (The Active Accessibility API
does not have helper methods specific to certain kinds of accessible objects.)

=for html <font face="Arial Narrow" size="-1"><table>

=for html <tr><td>Role constant</td><td>ActAcc Package</td></tr>

=for html <tr><td>ROLE_SYSTEM_TITLEBAR</td><td>

L<"Win32::ActAcc::Titlebar">

=for html </td></tr>

=for html <tr><td>ROLE_SYSTEM_MENUBAR</td><td>

L<"Win32::ActAcc::Menubar">

=for html </td></tr>

=for html <tr><td>ROLE_SYSTEM_MENUITEM</td><td>Win32::ActAcc::MenuItem</td></tr>

=for html <tr><td>ROLE_SYSTEM_MENUPOPUP</td><td>Win32::ActAcc::MenuPopup</td></tr>

=for html <tr><td>ROLE_SYSTEM_SCROLLBAR</td><td>Win32::ActAcc::Scrollbar</td></tr>

=for html <tr><td>ROLE_SYSTEM_GRIP</td><td>Win32::ActAcc::Grip</td></tr>

=for html <tr><td>ROLE_SYSTEM_SOUND</td><td>Win32::ActAcc::Sound</td></tr>

=for html <tr><td>ROLE_SYSTEM_CURSOR</td><td>Win32::ActAcc::Cursor</td></tr>

=for html <tr><td>ROLE_SYSTEM_CARET</td><td>Win32::ActAcc::Caret</td></tr>

=for html <tr><td>ROLE_SYSTEM_ALERT</td><td>Win32::ActAcc::Alert</td></tr>

=for html <tr><td>ROLE_SYSTEM_WINDOW</td><td>

L<"Win32::ActAcc::Window">

=for html </td></tr>

=for html <tr><td>ROLE_SYSTEM_CLIENT</td><td>Win32::ActAcc::Client</td></tr>

=for html <tr><td>ROLE_SYSTEM_TOOLTIP</td><td>Win32::ActAcc::Tooltip</td></tr>

=for html <tr><td>ROLE_SYSTEM_APPLICATION</td><td>Win32::ActAcc::Application</td></tr>

=for html <tr><td>ROLE_SYSTEM_DOCUMENT</td><td>Win32::ActAcc::Document</td></tr>

=for html <tr><td>ROLE_SYSTEM_PANE</td><td>Win32::ActAcc::Pane</td></tr>

=for html <tr><td>ROLE_SYSTEM_CHART</td><td>Win32::ActAcc::Chart</td></tr>

=for html <tr><td>ROLE_SYSTEM_DIALOG</td><td>Win32::ActAcc::Dialog</td></tr>

=for html <tr><td>ROLE_SYSTEM_BORDER</td><td>Win32::ActAcc::Border</td></tr>

=for html <tr><td>ROLE_SYSTEM_GROUPING</td><td>Win32::ActAcc::Grouping</td></tr>

=for html <tr><td>ROLE_SYSTEM_SEPARATOR</td><td>Win32::ActAcc::Separator</td></tr>

=for html <tr><td>ROLE_SYSTEM_TOOLBAR</td><td>Win32::ActAcc::Toolbar</td></tr>

=for html <tr><td>ROLE_SYSTEM_STATUSBAR</td><td>Win32::ActAcc::StatusBar</td></tr>

=for html <tr><td>ROLE_SYSTEM_TABLE</td><td>Win32::ActAcc::Table</td></tr>

=for html <tr><td>ROLE_SYSTEM_COLUMNHEADER</td><td>Win32::ActAcc::ColumnHeader</td></tr>

=for html <tr><td>ROLE_SYSTEM_ROWHEADER</td><td>Win32::ActAcc::RowHeader</td></tr>

=for html <tr><td>ROLE_SYSTEM_COLUMN</td><td>Win32::ActAcc::Column</td></tr>

=for html <tr><td>ROLE_SYSTEM_ROW</td><td>Win32::ActAcc::Row</td></tr>

=for html <tr><td>ROLE_SYSTEM_CELL</td><td>Win32::ActAcc::Cell</td></tr>

=for html <tr><td>ROLE_SYSTEM_LINK</td><td>Win32::ActAcc::Link</td></tr>

=for html <tr><td>ROLE_SYSTEM_HELPBALLOON</td><td>Win32::ActAcc::HelpBalloon</td></tr>

=for html <tr><td>ROLE_SYSTEM_CHARACTER</td><td>Win32::ActAcc::Character</td></tr>

=for html <tr><td>ROLE_SYSTEM_LIST</td><td>Win32::ActAcc::List</td></tr>

=for html <tr><td>ROLE_SYSTEM_LISTITEM</td><td>Win32::ActAcc::ListItem</td></tr>

=for html <tr><td>ROLE_SYSTEM_OUTLINE</td><td>

L<"Win32::ActAcc::Outline">

=for html </td></tr>

=for html <tr><td>ROLE_SYSTEM_OUTLINEITEM</td><td>

L<"Win32::ActAcc::OutlineItem">

=for html </td></tr>

=for html <tr><td>ROLE_SYSTEM_PAGETAB</td><td>Win32::ActAcc::PageTab</td></tr>

=for html <tr><td>ROLE_SYSTEM_PROPERTYPAGE</td><td>Win32::ActAcc::PropertyPage</td></tr>

=for html <tr><td>ROLE_SYSTEM_INDICATOR</td><td>Win32::ActAcc::Indicator</td></tr>

=for html <tr><td>ROLE_SYSTEM_GRAPHIC</td><td>Win32::ActAcc::Graphic</td></tr>

=for html <tr><td>ROLE_SYSTEM_STATICTEXT</td><td>Win32::ActAcc::StaticText</td></tr>

=for html <tr><td>ROLE_SYSTEM_TEXT</td><td>Win32::ActAcc::Text</td></tr>

=for html <tr><td>ROLE_SYSTEM_PUSHBUTTON</td><td>Win32::ActAcc::Pushbutton</td></tr>

=for html <tr><td>ROLE_SYSTEM_CHECKBUTTON</td><td>Win32::ActAcc::Checkbox</td></tr>

=for html <tr><td>ROLE_SYSTEM_RADIOBUTTON</td><td>Win32::ActAcc::Radiobutton</td></tr>

=for html <tr><td>ROLE_SYSTEM_COMBOBOX</td><td>Win32::ActAcc::Combobox</td></tr>

=for html <tr><td>ROLE_SYSTEM_DROPLIST</td><td>Win32::ActAcc::DropList</td></tr>

=for html <tr><td>ROLE_SYSTEM_PROGRESSBAR</td><td>Win32::ActAcc::ProgressBar</td></tr>

=for html <tr><td>ROLE_SYSTEM_DIAL</td><td>Win32::ActAcc::Dial</td></tr>

=for html <tr><td>ROLE_SYSTEM_HOTKEYFIELD</td><td>Win32::ActAcc::HotKeyField</td></tr>

=for html <tr><td>ROLE_SYSTEM_SLIDER</td><td>Win32::ActAcc::Slider</td></tr>

=for html <tr><td>ROLE_SYSTEM_SPINBUTTON</td><td>Win32::ActAcc::SpinButton</td></tr>

=for html <tr><td>ROLE_SYSTEM_DIAGRAM</td><td>Win32::ActAcc::Diagram</td></tr>

=for html <tr><td>ROLE_SYSTEM_ANIMATION</td><td>Win32::ActAcc::Animation</td></tr>

=for html <tr><td>ROLE_SYSTEM_EQUATION</td><td>Win32::ActAcc::Equation</td></tr>

=for html <tr><td>ROLE_SYSTEM_BUTTONDROPDOWN</td><td>Win32::ActAcc::ButtonDropDown</td></tr>

=for html <tr><td>ROLE_SYSTEM_BUTTONMENU</td><td>Win32::ActAcc::ButtonMenu</td></tr>

=for html <tr><td>ROLE_SYSTEM_BUTTONDROPDOWNGRID</td><td>Win32::ActAcc::ButtonDropDownGrid</td></tr>

=for html <tr><td>ROLE_SYSTEM_WHITESPACE</td><td>Win32::ActAcc::Whitespace</td></tr>

=for html <tr><td>ROLE_SYSTEM_PAGETABLIST</td><td>Win32::ActAcc::PageTabList</td></tr>

=for html <tr><td>ROLE_SYSTEM_CLOCK</td><td>Win32::ActAcc::Clock</td></tr>

=for html </table></font>

=head3 Win32::ActAcc::Window

=head4 mainMenu

Returns an AO for the main menu in the window.  Dies if there isn't one.  
This method relies on the characteristic "name" of the menus served by the default
Active Accessibility in Windows.  Apps that make their own custom menus,
such as Microsoft Word, may call the menu something different, in which
case mainMenu won't find it.

=head4 systemMenu

Returns an AO for the system menu in the window.  Dies if there isn't one.  The system menu is the inobtrusive
thingy in the title bar, which if you click it shows you choices including Close, Maximize, etc.

=head4 titlebar

Returns an AO for the window's titlebar.  Dies if it doesn't have one. 

=head4 menuPick (for Win32::ActAcc::Window)

Invokes a command from the application's main menu bar.  See L<"menuPick"> for Menubar.

=head3 Win32::ActAcc::Titlebar

=head4 btnMaximize

=head4 btnMinimize

=head4 btnClose

=head4 btnRestore

=head3 Win32::ActAcc::MenuItem

=head4 menuPick

 $aoNotepad->menuPick(+["File", "Exit"]);

menuPick uses the same CRITERIA as L<dig>.  You can specify each step as a string, a regexp, a CODE block, a hash, and whatnot.  

menuPick will not find menu items that are hidden since they are so boring that you have not chosen them recently.  So, 
before you run a script that relies on menuPick, you should "prime" the menu items the script will need, if they've
disappeared. 

menuPick will not find menu items that are scrolled out of view.

=head3 Win32::ActAcc::Outline

=head4 getRoot

 my $rootitem = $outline->getRoot();

The root item is the top item in the outline.  It is also the only
item at the lowest outline-level in the outline.

Active Accessibility weirdness note:  Outline items are all peers,
from the point of view of Active Accessibility.  They are all directly 
children of the outline object.  Hierarchy resides in the I<value> of 
an outline item.  Higher values nest inside lower values.  Relatedly,
the dig, drill, AccessibleChildren, etc., methods are not useful 
for traversing an outline.

=head3 Win32::ActAcc::OutlineItem

=head4 getLevel

Returns the outline-level of the outline item.  
The level is the Active Accessibility "value" of the item; this method just improves
the legibility of scripts that would otherwise be calling get_accValue.

Outer levels appear to have lower numbers than inner levels.

=head2 WinEvents

Using WinEvents, a Perl script can detect the consequences of its actions.  
For example, having "started" Notepad, the script must wait until Notepad comes up
and latch onto the new Notepad window (as opposed to some pre-existing Notepad window) 
before typing stuff into it.

Windows is continually emitting "events" such as EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, etc (see L<"EVENT constants">).
The ActAcc DLL receives these events and stores them in a circular buffer.
Perl scripts may poll that buffer using Win32::ActAcc::EventMonitor.
An EventMonitor is a cursor (or iterator) on the stream of events.

Normally you'll use the default EventMonitor.  If you need more than one cursor on the stream of events,
you can call L<"createEventMonitor"> to make a new event cursor.  Refer to the aaEvents sample.

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.  There's no overrun indicator on the circular
buffer, so try to keep your EventMonitors reasonably up-to-date 
if it's important not to miss any events.  
Circular buffer size (in events) for this build of ActAcc:

=constants AAEvtMon.h define BUF_CAPY_IN_EVENTS \((5000)\)

EventMonitors don't seem to pick up any WinEvents from I<Command Prompt>
windows in Windows 2000.  Perhaps these windows are owned by a process that resists
in-proc event hooks.  Hmm.

=head3 createEventMonitor

 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, which is how 
you generally want it.  

=head3 EventMonitor

Here are the methods on the EventMonitor object you get from createEventMonitor.

=head4 waitForEvent

Sometimes, you want to see I<whether> something happens.  Other times, you I<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'=>EVENT_OBJECT_SHOW(),
     'name'=>qr/Notepad/,
     'role'=>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 I<that> a Notepad windows has
appeared, but actually gets its Accessible Object for later use (such
as to I<close> the window).

You can omit the timeout, in which case waitForEvent patiently waits for a
matching event... which might never arrive. 

The hash's entries are:

=over 4

=item *

B<event>:  an event constant I<(remember the parentheses--see sample above)>.  See L<EVENT Constants>.

=item *

B<name> (optional): a regexp or string to match the name of the
accessible object of the event.  If it's a string, it must match
exactly--case matters and it must match the entire name.  

=item *

B<role> (optional):  a role constant that must match the accessible object of the event, e.g., ROLE_SYSTEM_WINDOW().  See L<ROLE Constants>.

=item *

B<hwnd> (optional):  only events on the specified HWND match.

=item *

B<aoToEqual> (optional):  only events on the specified AO (according to L<"Equals">) match.
If you're waiting for EVENT_OBJECT_DESTROY, use the "hwnd" member instead of aoToEqual.

=item *

B<code> (optional):  a CODE block that takes one argument, the event.  
Only events where the code block returns a true value match.

=back 4

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 can find out whether the event is I<already> in the circular buffer (and not already
retrieved by this EventMonitor) by specifying 0 for
the timeout.    

=head4 eventLoop

eventLoop is like waitForEvent, but takes a reference to a LIST of event criteria 
whereas waitForEvent takes just one.  

To decide between waitForEvent and eventLoop, you may:

=over 4

=item *

Always use eventLoop, the more flexible.

=item *

Model your need in the form of one of these three English sentences:  
(1) "Stand here and wait for
a guy wearing an orange hat", 
(2a) "Stand here and wait until you see either a guy wearing an orange hat or a kangaroo with a lollypop",
(2b) "Stand here until the alligator eats the butterfly and greet each kangaroo that passes by wearing an orange hat".
Sentences 2a and 2b would require eventLoop.

=back 4

 $eh->eventLoop( +[ EVENTCRITERIA, EVENTCRITERIA, etc. ], $timeoutSeconds );

You can put the event-response code into the 'code' key of the criteria hash, 
and make that code return a false value except when the eventLoop should end.

=head4 getEvent

 my $e = $eh->getEvent();
 if (defined($e)) { print $e->evDescribe() . "\n"; }

You will usually want to use waitForEvent.  But, just in case, there I<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. 

See L<"Win32::ActAcc::Event">.

=head4 dropHistory

 $eh->dropHistory(2000); # drop all but the most recent 2 seconds' events

=head4 clear

 $eh->clear();

Erases the backlog of events on the event monitor.

=head4 synch

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.)

=head4 isActive

 $a = $eh->isActive();

Returns a true value if the event monitor is active, a false
value if it is latent.

=head4 activate

 $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.

=head4 getEventCount

 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.)

=head4 debug_spin

This debug function displays the EventMonitor's events for a certain number of seconds.

 $eh->debug_spin(60);

=head3 Win32::ActAcc::Event

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 L<EVENT Constants>).  You can test it like this:

 next unless EVENT_OBJECT_VALUECHANGE()==$$e{'event'};

=head4 getAO

 $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.

=head4 AccessibleObjectFromEvent

Same as getAO.

=head4 evDescribe

 print $e->evDescribe() . "\n";

Good for debugging - returns some information about the event.

=head3 EventConstantName

Returns the C constant name for a WinEvent number defined in WinAble.h.
See L<EVENT Constants>.

=head3 AccessibleObjectFromEvent

Obtain an "accessible object" from information in a WinEvent.  
(You may prefer to use the object-oriented $e->L<"getAO">() way instead.)

 my $accObj = AccessibleObjectFromEvent($$e{'hwnd'}, $$e{'idObject'}, $$e{'idChild'});

=head2 Tuneable Parameters

 $Win32::ActAcc::MenuItem::BetweenClicksToCloseThenOpen = 0.25; # seconds
 $Win32::ActAcc::MenuItem::MenuPopupRetrospective = 750; # milliseconds
 $Win32::ActAcc::MenuItem::MenuStartTimeout = 3; # seconds
 $Win32::ActAcc::MenuIterator::HoverDwell = 0.25; # seconds

=head2 Windows Shell

=head3 StartButton

StartButton obtains an "accessible object" representing the Start button:

 $ao = Win32::ActAcc::StartButton();

=head3 StartButtonMenu

 use Win32::ActAcc::Shell2000;
 #
 Win32::OLE->Initialize();
 $menu = Win32::ActAcc::Shell2000::StartButtonMenu();
 Win32::ActAcc::clearEvents();
 $menu->menuPick([ qr/^Programs/, qr/Accessories/i, qr/Notepad/i ]);

StartButtonMenu clicks the Start button, waits for a menu to come up, and returns the menu object.

 $ao = Win32::ActAcc::StartButtonMenu();

For working with menus, see L<"Win32::ActAcc::Menubar">.

=head2 Tools

=head3 aaDigger.pl

aaDigger lets you navigate the hierarchy of accessible objects, 
rooted at the Desktop window.  With aaDigger, you can see the world
the way ActAcc sees it -- which can be quite helpful when you are trying
to write a Perl script.  aaDigger has its own L<manpage|aaDigger>.

You can invoke aaDigger from within a script, in case the script is getting
to a certain point ok but you need to figure out what it should do next:

 use Win32::ActAcc::aaExplorer;  
 
 my $ao = ...
 Win32::ActAcc::aaExplorer::aaExplore($ao);

You can also invoke aaDigger's "tree" feature from within a script:

 $ao->debug_tree();

=head3 aaEvents.pl

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.

You can invoke aaEvents from within a script, in case the script is getting
to a certain point ok but you need to figure out what it should do next:

 # you must already have $eh: eg, $eh = Win32::ActAcc::createEventMonitor(1);
 $eh->debug_spin(60);  # look at the events for 60 seconds

=head3 aaWhereAmI.pl

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'll discover
some things with aaWhereAmI that you might not find any other way.

=head1 BUGS, LIMITATIONS, AND SHORTCOMINGS

menuPick can't choose commands that are helpfully hidden because you
have not used them recently, nor commands that you'd have to scroll
to expose.

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.

EventMonitors install 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.

Event monitors require Perl scripts to use a Giant Switch technique 
that gets ugly.  A callback veneer should be applied on top.

There's no "brake pedal" for those awkward moments when you want
to stop or pause the script, but it keeps tearing the mouse away from you.
(You can generally derail a script with the Secure Attention Sequence
Ctrl+Alt+Del, since Win32::ActAcc can't operate the logon desktop.)

A single IAccessible* + object ID may be referenced by innumerable
Win32::ActAcc::AO objects.

The Perl thread isn't shielded against IAccessible* calls crashing or returning nonsense data
causing the Perl thread to crash.  (It's surprising how seldom this seems to happen!, but
someday we should shore up the defenses.)

=head1 INSTALLATION

You can install Win32::ActAcc by compiling it from source code, or,
if you have ActivePerl, you can install it using PPM, in which
case you don't need a C++ compiler.

=head2 Installation from source code

 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.

The test is tenuous.  It will probably work only with Windows 2000,
since the design and operation of Notepad changes subtly from 
version to version.  You must have Win32::GuiTest 0.6 or later.

Prerequisites:

=over 4

=item *

You may need Visual C++ 6.0 SP 4.  The C/C++ part of Win32::ActAcc might not
be portable to other compilers.

=item *

You need the July 2000 "Platform SDK".  
Earlier versions of the Active Accessibility SDK could give problems compiling.

=item *

The test suite requires Notepad.exe and Explorer.exe on the path.  Also, it requires
Win32::GuiTest.

=item *

The Eliza-AOLInstantMessenger sample requires up-to-date HTML parsing
modules.  It will tell you if yours are missing or out-of-date.

=back 4

=head2 Installation for ActivePerl users (PPM)

ActivePerl users can install Win32::ActAcc using PPM.  

=over 4

=item 1

Unzip the zip (Win32-ActAcc-n.n.zip).  Make sure your unzip
program preserved the directory tree: for example, you should see
Win32-ActAcc.tar.gz in an "x86" subdirectory under the directory that
contains ActAcc.html (the documentation).

=item 2

Open a command prompt window.

=item 3

In the command prompt, "cd" to the directory that contains ActAcc.html.

=item 4

In the command prompt, issue the following command.

 ppm install --location=. Win32-ActAcc

=back 4

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.

=head2 Files Installed

=over 4

=item *

In bin:  aaDigger.bat and aaDigger.pl, aaEvents.bat and aaEvents.pl, 
aaWhereAmI.bat and aaWhereAmI.pl

=item *

In site\lib\Win32:  aaDigger.pl, aaEvents.pl, aaWhereAmI.pl, ActAcc.pm, ActAcc.pod

In site\lib\Win32\ActAcc:  aaExplorer.pm

=item *

In site\lib\auto\Win32\ActAcc:  ActAcc.dll, ActAccEM.dll

=back 4

=head1 APPENDIX - CONSTANTS

These are the standard Active Accessibility "constants", made accessible to Perl scripts.
Use Win32::ActAcc constants as though they were functions:

 die unless (0 == CHILDID_SELF());

=head2 EVENT constants

=constants ActAcc.xs CONST_TEST\((EVENT_.*)\)

=head2 OBJID constants

=constants ActAcc.xs CONST_TEST\((OBJID_.*)\)

=head2 STATE constants

=constants ActAcc.xs CONST_TEST\((STATE_.*)\)

=head2 ROLE constants

=constants ActAcc.xs CONST_TEST\((ROLE_.*)\)

=head2 SELFLAG constants

=constants ActAcc.xs CONST_TEST\((SELFLAG_.*)\)

=head2 NAVDIR constants

=constants ActAcc.xs CONST_TEST\((NAVDIR_.*)\)

=head1 COPYRIGHT

Copyright 2001, Phill Wolf.  All rights reserved, including, without limitation, motion-picture rights.

You may use Win32::ActAcc under the terms of the Artistic License, as
specified in the README file of the Perl distribution.

=head1 AUTHOR

Phill Wolf, pbwolf@cpan.org

=head1 SEE ALSO

=over 4

=item *

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

=item *

Win32::OLE

=item *

Win32::GuiTest

=item *

Net::AIM

=item *

"The automation imperative" section of: Black-box Testing by Boris Beizer. Wiley, 1995.

=back 4

=cut
