The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Win32::CtrlGUI::State - OO system for controlling Win32 GUI windows through a state machine

VERSION

This document describes version 0.32 of Win32::CtrlGUI::State, released January 10, 2015 as part of Win32-CtrlGUI version 0.32.

SYNOPSIS

  use Win32::CtrlGUI::State;

  Win32::CtrlGUI::State->newdo(
    seq => [
      atom => [criteria => [pos => qr/Notepad/],
               action => "!fo"],

      seq_opt => [
        seq => [
          atom => [criteria => [pos => 'Notepad', qr/^The text in the .* file has changed/i],
                   action => "!y"],

          dialog => [criteria => [pos => 'Save As'],
                     action => "!nC:\\TEMP\\Saved.txt{1}{ENTER}",
                     timeout => 5,
                     cnfm_criteria => [pos => 'Save As', qr/already exists/i],
                     cnfm_action => "!y"],
        ],

        dialog => [criteria => [pos => 'Open', 'Cancel'],
                   action => "!n{1}".Win32::GetCwd()."\\test.pl{1}{HOME}{2}{ENTER}"],
      ],

      dialog => [criteria => [pos => qr/Notepad/],
                 action => "!fx"],
    ]
  );

DESCRIPTION

Win32::CtrlGUI::State is used to define a set of state, the desired response to those state, and how those states fit together so as to make it easier to control Win32 GUI windows. Think of it as intelligent flow-control for Win32 GUI control. Also, it lets you use a Tk debugger to observe your scripts as they execute.

The system itself is object-oriented - there are a number of types of states, most of which accept a list of other states as parameters. If you think about it, code-blocks are objects. So are if-then statements. So, rather than write my own language and parser for doing flow-control of GUI windows, I made an OO system within Perl. Much easier than writing a parser.

The basic state subclasses are:

atom

These are used to specify single "events" in the system. Passed to the constructor are a set of criteria and the action to take when those criteria are met. If that atom is currently active and the criteria become met, the action will be executed. It also takes on optional timeout parameter.

multi

This is an abstract parent class intended to support such classes as seq, seq_opt, fork, and loop. The preferred syntax for passing states to multi subclasses is:

  multi => [
    parameter => value,
    state1_class => [ state1 parameters ],
    state2_class => [ state2 parameters ],
  ],

Alternate legal syntaxes include:

  multi => [
    [state1_class => state1 parameters],
    Win32::CtrlGUI::State:state2_class->new(state2 parameters),
  ]

That is to say, multi class objects expect their parameter array to consist of a sequence of these four "entities" (which can be alternated as desired):

  • parameter => value pairs

  • state_class => array ref to state parameters pairs

  • array ref to state1_class, state parameters

  • Win32::Ctrl::GUI::State class object

seq

The passed states will be waited for one-by-one and the actions executed. No state is allowed to be skipped.

seq_opt

This state is similar to seq, except that any state may be skipped except for the last one. That is to say, execution will "jump" to whichever state shows up first. Once a state has been jumped to, the previous states will not be executed. The last state in the list is sometimes referred to as the exit criteria.

fork

The first state to be met will be executed and none of the others will. Think of it as a select-case statement. Of course, seq and seq_opt states can be passed to the fork state.

loop

Lets you do loops:) Loops take two optional parameters - timeout and body_req and either one or two states. The first state is the "body" state and the second the "exit" state. I strongly encourage the use of the dialog state when building loops (this is especially critical for loops where the body only has one state - otherwise, simple atoms may trigger multiple times off of the same window).

dialog

The dialog state was created to deal with a common problem, that is to say waiting for a window to pop up, sending it text, and then waiting for it to disappear. In addition, the dialog state takes an optional set of parameters for a "confirmation" window. If the confirmation window shows up before the original window disappears, the confirmation action will be executed. The dialog state is implemented using a seq state and, if there is a confirmation specification, a seq_opt state. Note that waiting for the window to disappear is based on the window handle, not on the criteria, which makes this safe to use in loops.

Of note, if you pass a multi state to another multi state, remember that the "child" state has to finish executing before the parent can continue. For instance, in the following code, if the window "Foo" is seen, seeing the window "Done" will not cause the loop to exit until the window "Bar" has been seen.

  Win32::CtrlGUI::State->newdo(
    loop => [
      seq => [
          dialog => [criteria => [pos => 'Foo'], action => '{ENTER}'],
          dialog => [criteria => [pos => 'Bar'], action => '{ENTER}'],
      ],
      seq => [
          atom => [criteria => [pos => 'Done'], action => '{ENTER}'],
      ],
    ]
  );

METHODS

new

The first parameter to the new method is the subclass to create - atom, seq, seq_opt, etc. The _new method for that class is then called and the remaining parameters passed.

_new

The default _new method takes a list of hash entries, places the object in the init state, and returns the object.

newdo

This calls new and then do_state. It returns the Win32::CtrlGUI::State object after it has finished executing.

is_recognized

This is a generic method and has to be overriden by the subclass. When is_recognized is called, it should return true if this state is currently or has ever been recognized (once a path is followed, the path needs to be followed until the end.)

wait_recognized

This will wait until a given state has been recognized.

do_action_step

Because the whole system is capable of being driven in an asynchronous manner from the very top (which makes it possible to run the Win32::CtrlGUI::State system from within Tk, for instance), actions need to be executable in a non-blocking fashion. The method call do_action_step is crucial to that. Remember that there is an action "delay", so do_action_step will keep returning, but not setting the state to done, until that delay is used up and the action can actually be executed. The system does not yet allow for multi-part actions in and of themselves (for instance, it will still block if a sendkeys action involves internal delays).

wait_action

This will wait until the action for a given state has been completed. It should only be called after is_recognized returns true.

do_state

This will wait until the state is recognized (by calling wait_recognized) and then execute the action (by calling wait_action).

reset

The reset method automagically resets the state as if nothing had ever happened.

STATES

It is important to note that Win32::CtrlGUI::State objects can be in one of six different states. They are:

init

This is the state before the object has had any methods invoked on it.

srch

This is the state the object enters after is_recognized is first called on it, but before the desired state has been recognized. Distinguishing between <init> and <srch> allows time outs to be implemented.

rcog

This is the state the object enters after its criteria are first recognized.

actn

This is the state the object enters when do_action_step is first called.

done

This is the state the object enters after the action is fully completed.

fail

This is the state the object enters when a time out has occurred (this doesn't apply to loop states, but does apply to atom states).

CONFIGURATION AND ENVIRONMENT

Win32::CtrlGUI::State requires no configuration files or environment variables.

INCOMPATIBILITIES

None reported.

BUGS AND LIMITATIONS

No bugs have been reported.

AUTHOR

Toby Ovod-Everett <toby AT ovod-everett.org>

Win32::CtrlGUI is now maintained by Christopher J. Madsen <perl AT cjmweb.net>

Please report any bugs or feature requests to <bug-Win32-CtrlGUI AT rt.cpan.org> or through the web interface at http://rt.cpan.org/Public/Bug/Report.html?Queue=Win32-CtrlGUI.

You can follow or contribute to Win32-CtrlGUI's development at http://github.com/madsen/win32-ctrlgui.

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Toby Ovod-Everett.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.