Using Win32::GuiTest

Piotr Kaluski

www.piotrkaluski.com


        
        

This is version 1.9

Copyright

Permission is granted to copy, distribute and/or modify this document under the terms of the Open Publication License, version 2.0.

$Date: 2006/06/03 12:00:00 $

Revision History
Revision 1.903 June 2006pkaluski
Corrected documentation for IsGrayedButton
Revision 1.827 January 2006pkaluski
Corrected documentation for IsWindowStyle
Revision 1.730 November 2005pkaluski
Updated documentation for GetListViewContents
Revision 1.62 October 2005pkaluski
Added description of GetPopupHandle
Revision 1.523 September 2005pkaluski
Reference part reshaped. I think it looks better now
Revision 1.415 September 2005pkaluski
Updated documentation for release 1.50.4. Started reshaping reference part
Revision 1.327 August 2005pkaluski
Ran spell checker. Added some corrections suggested by Gabor Szabo
Revision 1.214 August 2005pkaluski
Added more advanced part to tutorial
Revision 1.18 May 2005pkaluski
Tutorial on GUI Testing is now a chapter of this book
Revision 1.05 May 2005pkaluski
All exported functions are documented
Revision 0.31 May 2005pkaluski
More functions added. Around 50% of functions documented
Revision 0.227 April 2005pkaluski
More functions added. Still many remain to be documented
Revision 0.126 April 2005pkaluski
Initial revision

Table of Contents

1. Introduction
Downloading this documentation
Intended audience
Installing Win32::GuiTest
Some guidelines on using this documentation
Asking further questions
2. GUI testing - tutorial
Prerequisites
Let's start
Going further
More advanced topics
Summary
3. Win32::GuiTest functions overview
4. Windowing, identification and general purpose functions
Finding windows/windows handle
General windowing functions
Process related functions
5. Controls related functions
General controls related functions
Common controls
Buttons
List boxes
Combo boxes
Other controls
Microsoft's tab controls
Microsoft's List-View controls
Microsoft's Tree-View controls
6. Mouse and screen functions
7. Keyboard functions
8. Menu functions
9. Appendix - functions in alphabetical order
AllocateVirtualBuffer
CheckButton
ClientToScreen
EnableWindow
FindWindowLike
FreeVirtualBuffer
GetActiveWindow
GetCaretPos
GetChildDepth
GetChildWindows
GetClassName
GetComboContents
GetComboText
GetCursorPos
GetDesktopWindow
GetFocus
GetForegroundWindow
GetListContents
GetListText
GetListViewContents
GetMenu
GetMenuItemCount
GetMenuItemIndex
GetMenuItemInfo
GetParent
GetPopupHandle
GetScreenRes
GetSubMenu
GetSystemMenu
GetTabItems
GetTreeViewSelPath
GetWindow
GetWindowID
GetWindowLong
GetWindowRect
GetWindowText
IsCheckedButton
IsChild
IsGrayedButton
IsKeyPressed
IsListViewItemSel
IsTabItemSel
IsWindow
IsWindowEnabled
IsWindowStyle
IsWindowStyleEx
IsWindowVisible
MenuSelect
MouseClick
MouseMoveAbsPix
MouseMoveWheel
NormToScreen
PostMessage
PushButton
PushChildButton
PushChildById
ReadFromVirtualBuffer
ScreenToClient
ScreenToNorm
SelComboItem
SelComboItemText
SelComboString
SelectTabItem
SelListViewItem
SelListViewItemText
SelTabItem
SelTabItemText
SelTreeViewItemPath
SendKeys
SendLButtonDown
SendLButtonUp
SendMButtonDown
SendMButtonUp
SendMessage
SendMouse
SendMouseMoveRel
SendMouseMoveAbs
SendRawKey
SendRButtonDown
SendRButtonUp
SetActiveWindow
SetFocus
SetForegroundWindow
SetWindowPos
ShowWindow
TabCtrl_GetCurFocus
TabCtrl_GetItemCount
TabCtrl_SetCurFocus
TabCtrl_SetCurSel
WaitForReady
WaitWindow
WaitWindowLike
WindowFromPoint
WMGetText
WMSetText
WriteToVirtualBuffer
10. Recommended reading

List of Examples

2.1. Getting a contents of Edit control in C
2.2. Getting a contents of Edit control in perl
2.3. Getting a contents of Edit control in perl (2nd attempt)
2.4. Getting a a text of an item in ListView control in perl
2.5. Getting a a text of an item in ListView control in C
2.6. Getting a contents of list view in perl
9.1. Getting all windows (apart from desktop)
9.2. Finding calculator window
9.3. Finding a button of id=123, which is a direct child of the $parent
9.4. Getting a path
9.5. Exit foreground application through application menu
9.6. Exit foreground application through system menu
9.7. Click on CE button if its parent window is in foreground
9.8. Right click on CE button if its parent window is in foreground
9.9. Click on 8 button window under the specified parent window
9.10. Click on Calculator parent window itself
9.11. Select first item, clears out any previous selections
9.12. Select an *additional* item
9.13. Select first item, clears out any previous selections
9.14. Select an *additional* item
9.15. Select Machine item and Processors sub-item
9.16. How should I title this one???
9.17. Finding calculator window (giving it 20 seconds to load)

Chapter 1. Introduction

This document is intended to be a comprehensive guide and a complete reference to Win32::GuiTest perl module (pretty ambitious, isn't it). Win32::GuiTest is perl module for automation of operations on Win32 GUI interface. It provides a set of methods for manipulating window handles, controls and to simulate user input.

Downloading this documentation

If you want to download this documentation in order to access it, when you are offline, you can get it from here. It is an HTML document, but in one chunk, so it is easier to get. I would like to have it converted to pdf but had no luck trying this, nor I had time to try harder. If you are experienced in converting docbook to pdf let me know.

Intended audience

You have to know perl in order to use this document effectively. As of this writing, there is no GUI or IDE allowing to record and playback automation scripts. Although I consider such tools less useful than it is believed, it is natural to expect that such a tool exists for Win32::GuiTest. Unfortunately such a tool does not exist. I also do not believe that you can be an effective test automator if you do not have programming skills.

Installing Win32::GuiTest

For the most recent distributions (and the previous ones) you should look on Source Forge. Released packages contain standard directory structure created by h2xs and files Win32-GuiTest.ppd and Win32-GuiTest.tar.gz which are all that you need for ppm. See ppm documentation for details.

Some guidelines on using this documentation

Please read these few comments since they may help you in better understanding of this document. They will also help you to further explore the topic of GUI automation.

I am using a term "Win32" to refer to Windows operating system family : windows 98/NT/2000/XP.

"Win32::GuiTest" refers to perl library.

If you read a description of a function and you find a sentence "This is a simple wrapper around Win32 function" that means that you can find more details on how the function works on Microsoft's MSDN. I intentionally refrained from providing a link for a function description, since it tends to change every 1-2 years. But if you enter www.msdn.com and make a search for a function, for example "SetForegroundWindow", you should get API description as a first result.

Asking further questions

If you have further questions about how to use Win32::GuiTest or have some problem, which you don't know how to solve, please search perlguitest group at yahoo: http://groups.yahoo.com/group/perlguitest. Some obvious questions like "is Win32::GuiTest suitable for java (it isn't)" has been answered many, many times, so please spend this 5 minutes for doing a simple search.

If you can't find an answer, then post your question.

Please do not start by sending a question to me directly. If it is a simple question I will simply ignore it. If it is not a simple question I may consider helping you, but there is a cost involved. I am a busy person, and I am reluctant in doing somebody's else homework. However, I would love to see Win32::GuiTest being popular and widely used. Important factor in increasing software popularity is a good portfolio. And this is the price you will have to pay. If you want my bigger involvement in your specific problem I want you to write an article on how you use Win32::GuiTest in your company or at least providing me with some materials, which would allow me to write this article. And I will expect you to testify, that this is true. I think such an agreement is beneficial for all of us. The more popular the tool is, the more likely you are to get help next time you have a problem. Secondly, your company image will gain. Using Open Source is trendy, and you will look really smart if you show that instead of spending tons of dolars on comercial tools you could get the same value for free.

Chapter 2. GUI testing - tutorial

This chapter may serve as a tutorial on 2 topics - using perl module Win32::GuiTest and on the basics of automated testing of Gui applications. The intended audience are perl developers, who want to use Win32::GuiTest, and all other people who maybe interested in knowing what is automated GUI testing all about.

Prerequisites

You may just read the tutorial. It should give a good understanding of how is GUI automation implemented. But it would be much more effective if you practice all examples, which are given in this document. In order to do it, you should have the following software in place:

Let's start

Although it is not always true we can say that generally, all windows which are opened on your screen are system objects. Win32 keeps track of them and can give information about them. Let's practice from the very beginning. Launch the calculator application available in Win32 systems. On my machine it looks like this:

If it does not look like this on your machine, go to "View" menu in Calculator and choose "standard". Although keeping "scientific" will not do any harm, using the standard version will help us avoid confusion.

Now run WinSpy.

Click the "Full screen" button as shown above...

and then "More" to get the window given below:

On the right side, you can see a tree, reminding a tree of catalogs. Find an item, which is named exactly in the same way, as your Calculator window. The title of the window, also called caption is placed here. In my case it is "Calculator". If you use Win32 with different language, the title may differ. Whatever the title, try to find an item with this title in WinSpy tree.

Got it? Now place Calculator and WinSpy in a way that they don't overlap so you can see them both. Click on the item you've just found in WinSpy and click "Flash" button in the bottom right corner of WinSpy window. Did you notice that? Borders of Calculator were blinking for a moment. This feature helps you to make sure that the item from the tree relates to the right window. Try to experiment with other items. Go to the top of the tree. Choose "Desktop window" item. Click "Flash". Frame of the the whole screen blinks. Try with other items as well.

Once you played a little bit, we can come back to Calculator.

Imagine that you want to automate the following scenario:

  • Using keyboard calculate 2+5.

It requires that you press the following keys: 2, +, 5 and =.

If a user want to do such an operation on Calculator, he/she has to do the following:

  • Launch the Calculator application or if it is opened - click on it.

  • Type the right keys

Actually, in the step one, clicking on the opened application (or using Alt-Tab to switch to this application) is a way of doing something important. You move the "input focus" to Calculator. In Win32, window needs to have a focus in order to receive all input from the keyboard. When you have several applications opened, and you type something, only one application, this with the input focus, actually react on what you type.

OK. We have prepared the first test case scenario. Let's write a perl script, which will do it for us. Let's assume that Calculator application is opened when the perl script starts.

Firstly the script has to move the input focus to Calculator. But which window is Calculator? And how to manipulate this window?

We will need to use the function FindWindowLike:

    use Win32::GuiTest qw( FindWindowLike );
    use strict;
    my @whnds = FindWindowLike( undef, "^Calculator" );
    if( !@whnds ){
        die "Cannot find window with title/caption Calculator\n";
    }else{
        printf( "Window handle of calculator application is %x\n", $whnds[ 0 ] );
    }

Of course, if you are using Win32 for different language (like Polish), You will have to change the search title to the right one ("Kalkulator" for Polish).

FindWindowLike returns a list of window handles. Window handle uniquely identifies a window in the system. In any time, there could be only one window with the given window handle, which is a long number.

Why does it return a list? We want only one window, don't we? FindWindowLike is a flexible function, which allows to specify search conditions for the group of windows. In that case, it will return handles of all windows, which satisfy these conditions. In our call, we specify that we are looking for a window with title "Calculator". In most cases only Calculator window will match. However, if there is another window opened which contains "Calculator" string in its title, its handle will also be returned. The second parameter of FindWindowLike function is treated as a regular expression to match with all windows' titles.

Try to run it now. If your calculator application is opened you should get something like:

Window handle of calculator application is 103B6 (hex). Note that it matches the window handle shown by WinSpy on the picture above. Remember - WinSpy shows most of numbers in hexadecimal notation. For perl, the default notations is decimal. Keep that in mind while looking for reasons, why perl script does not display the handle displayed by WinSpy.

So we have found the window. Now we have to move focus to the window and then type the right keys.

We move focus using function SetForegroundWindow. And we send keys using SendKeys.

Our script will look like this:

    use Win32::GuiTest qw( FindWindowLike
                           SetForegroundWindow
                           SendKeys );
    use strict;
    my @whnds = FindWindowLike( undef, "^Calculator" );
    if( !@whnds ){
        die "Cannot find window with title/caption Calculator\n";
    }else{
        printf( "Window handle of calculator application is %x\n", $whnds[ 0 ] );
    }

    SetForegroundWindow( $whnds[ 0 ] );
    SendKeys( "2{+}5=" );

SetForegroundWindow takes a handle to a window, which should receive the input focus. The SendKeys sends the keys to the window, which has the input focus. "+" has a special meaning for SendKeys so it has to be taken in braces.

Let's try. When you run the script, the Calculator's window will move to front and then it will display "7" (before it displays "7", it will also display "2" and "5", however it would be done so quickly, that you will not notice that).

That was easy. Let's go a step further. You can input data into Calculator in 2 ways - by keyboard or by clicking the right buttons on calculator's panel. It's time to test the second way of using Calculator.

Have a look at WinSpy again. Notice that Calculator item in WinSpy tree has a plus. Plus suggests that you can expand an item and find something more in it. Let's do it.

You can see more items. What are they? Well, check it yourself. Try to highlight them and see what blinks. You will quickly realize that these items are Calculator's buttons and display. They are windows too! Windows, which have some characteristics different from Calculator's main window, but they are windows.

Find the window, which is a "2" button. Click it. Look what WinSpy says about it. It gives you the window handle. It also display information about control id.

Each window has a control id. It does not have any particular meaning for main windows, however, it does for windows, which belong to other window (are children of other window). Such windows (belonging to other window) are also called controls. Control id is used to uniquely identify child window among other children on the same parent window (this is not always true. It may happen that a parent have several children with the same id). Find all buttons we need and write down their control ids. They should be:

ButtonControl id (Hex)Control id (Decimal)
"2"7E126
"5"81129
"+"5C92
"="70112

Notice, that control ids are static. This means, they are always the same for each instance of the same application. Control id for "2" button is 7E on my machine and is also 7E on your machine. Control ids are given to controls when the program is designed. They are hard coded in the program. Window handles are not. If they are the same on my pictures and your machine it's a pure accident. Window handles are dynamic. A window is given a handle every time it is created by the system. If 2 instances of the same application are created (say, you will run Calculator twice), they will have totally different set of windows' handles.

Our "buttoned" test will look like this:

  • Find a window

  • Push all necessary buttons.

You push a button by calling PushChildButton. It takes 2 arguments : window handle of the window on which the button is placed (parent window), and the control id of the button you want to push.

Here is the code:

    use Win32::GuiTest qw( FindWindowLike
                           PushChildButton );
    use strict;
    
    my @whnds = FindWindowLike( undef, "^Calculator" );
    if( !@whnds ){
        die "Cannot find window with title/caption Calculator\n";
    }else{
        printf( "Window handle of calculator application is %x\n", $whnds[ 0 ] );
    }
    PushChildButton( $whnds[ 0 ], 126 ); # Button 2
    PushChildButton( $whnds[ 0 ], 92 );  # Button +
    PushChildButton( $whnds[ 0 ], 129 ); # Button 5
    PushChildButton( $whnds[ 0 ], 112 ); # Button =

Notice that you do not have to move the input focus to Calculator. That's because you specify exactly, which button in which window you want to push.

Run it. Again, Calculator should display 7.

We are now able, to make the script doing typing and pushing for us. The really automated test also requires that the results are automatically checked. So the thing we miss is checking if when adding 2 and 5 Calculator actually displays 7.

We have to go back to WinSpy again. On the very beginning of controls belonging to Calculator, there should be a control of type "Edit". As you may guess, Edit control is also a window, with some special features, like displaying a text. You get the contents of the Edit control by calling WMGetText. It takes as a parameter a window handle of the Edit control. So in order to use it in our code, we have to find out a window handle for the Edit control. We actually have to implement finding this handle. We cannot hard code it, since you never know what would be the window handle of any window. But when you have the control id and window handle of a window, which is a parent of the Edit control, you can easily get window handle of that control. The function, which is going to help you is again FindWindowLike.

First the script, then the explanation:

    
    use Win32::GuiTest qw( FindWindowLike
                           PushChildButton
                           WMGetText );
    use strict;

    my @whnds = FindWindowLike( undef, "^Calculator" );
    if( !@whnds ){
        die "Cannot find window with title/caption Calculator\n";
    }else{
        printf( "Window handle of calculator application is %x\n", $whnds[ 0 ] );
    }
    PushChildButton( $whnds[ 0 ], 126 ); # Button 2
    PushChildButton( $whnds[ 0 ], 92 );  # Button +
    PushChildButton( $whnds[ 0 ], 129 ); # Button 5
    PushChildButton( $whnds[ 0 ], 112 ); # Button =

    my $edit_ctrl_id = 403; #Edit window, 193 Hex
    my @edit = FindWindowLike( $whnds[ 0 ], undef, "^Edit", $edit_ctrl_id );
    if( !@edit ){
        die "Cannot find window handle for Edit control\n";
    }else{
        printf( "Edit window handle is %x\n", $edit[ 0 ] );
    }
    my $result = WMGetText( $edit[ 0 ] );
    if( $result != 7 ){
        print "Test failed. The result is $result and expected value was 7\n";
    }else{
        print "Success. The result is $result, which is as expected\n";
    }

Note, that in the second call of FindWindowLike you don't have to give "^Edit" regular expression as a class name. Parent window and control id, in that particular situation, is enough. But we will use this redundancy as a fuse.

As you can see, the only thing we add is finding window handle of edit window and then get text from this window. Then the text is compared with the expected value.

You should get something like this:

Note: this time main window handle is different. This is because I closed Calculator and ran it again. As you already know, it was given a different window handle during the second run.

Congratulations! You've done the fully automated GUI test.

Going further

As you can see, the basic concepts behind automated GUI testing are not that difficult. However, I have some bad news for you. Gui testing is more complex then it appears after reading this tutorial. The one object - one window pattern is not followed even for some basic controls. One of them is toolbar. If you examine with WinSpy any application containing a toolbar, you will see that WinSpy sees only one window - the toolbar. Buttons on the toolbar are not separate windows. So you can't work with a toolbar in a way you did with calculator. We need to use some more sophisticated mechanisms.

Also, some types of applications are seen by the system as one window with no children. Java applications behave this way. No matter how many controls they have, they are seen as single window by Win32 (and, what follows, by WinSpy).

But there is still much interesting stuff you can do with Win32::GuiTest perl module.

What you got in this tutorial should be enough to do simple test scripts. However, if you plan to perform some more serious testing of applications, which are more complex than calculator, sooner or later the knowledge from the first part of this tutorial will be insufficient. Have a look at the functions' descriptions in the appendix.

The next part of this tutorial addresses dealing with advanced controls. It is significantly more advanced then the first part of the tutorial. You don't have to understand it in order to be able to do useful/advanced automation using Win32::GuiTest. However, it does address some issues, which may appear useful, when you deal with custom, non-standard controls. It also explains in more detail, how Windows controls work. Although it is not going to answer all your questions, it should give you a background for finding a solution to some problems you will encounter. In order to understand the next part of the tutorial you should have some knowledge (or at least a will to understand) of C, perl (of course) and perl internals. I will do my best to make it simple, but if you have some programming skills it will definitely help.

Fasten your sitbelts...

More advanced topics

In general (and this is a pretty good generalization) you communicate with windows by sending messages. Whatever you want from a control (which is a window too) - you send it a message. You send a message using SendMessage function. You can follow the link but I will place a function description here, so it's easier to check:

$result = SendMessage($hwnd,  
 $msg,  
 $wParam,  
 $lParam); 
 $hwnd - Handle of a window, to which a message is sent. ;
 $msg - Message id ;
 $wParam - Specifies additional message-specific information ;
 $lParam - Specifies additional message-specific information ;

Message id is integer identifying a command, wParam and lParam are additional command's parameters. Their meaning depends on the command (message id). The important thing to remember is that all parameters are numbers. Some of them can be interpreted as pointers, but they are numbers. The best way to explain it would be an example. Imagine that you want to control and Edit Box control. Again, we will use calculator as an example application. We want to get contents of the display. We have done this already in the first part of the tutorial, but we did that by calling Win32::GuiTest function, which did all the messaging for us. Now we will do it ourselves, in order to better understand how it all works.

You get a contents of an edit box by sending it a message WM_GETTEXT. If you do a search in MSDN you should find a detailed description of WM_GETTEXT (I intentionally refrain from giving you detailed link to message's documentation. Microsoft loves changing things, and documentation in no exception. Whatever link I give you, it will be broken in a year or two). It should look something like this:

If you send such a message then it is expected that 4th parameter is a pointer to the buffer to which the contents of edit box will be copied. If you use C, the code would look something like this:

Example 2.1. Getting a contents of Edit control in C


    int main(int argc, char* argv[])
    {
        HWND hWnd = HWND( 0x204ba );
        char buffer[ 100 ];

        SendMessage( hWnd, WM_GETTEXT, 100, LPARAM( buffer ) );

        printf("The result from Calculator is %s\n", buffer );
        return 0;
    }

If you run it you should get the correct value printed on the screen. Note that you had to provide the window handle of an Edit control. You can get it easily using WinSpy. Implementing the mechanism for finding the window handle in C would take too much time and would distract us from the point.

We have the C code working. Let's quickly write an equivalent in perl:

Example 2.2. Getting a contents of Edit control in perl


    use Win32::GuiTest qw( SendMessage );
    use strict;
    # WM_GETTEXT is 0xD
    my $msg_id = 0xd;
    my $hwnd = 0x204ba;
    my $buffer = " " x 100;
    SendMessage( $hwnd, $msg_id, 100, $buffer ); 
    print "The result from Calculator is $buffer\n";

If you are lucky your test script will crash immediately. If not it will continue working, but something bad would happen behind the scenes anyway.

What is wrong with the code? In order to understand the problem we will have to talk a little bit about perl internals. In C code, buffer is a pointer to place in memory where the string is to be stored. In perl, a scalar value $buffer is internally represented as a structure. The structure stores information about the type, and other information and, of course, a pointer to a memory containing the actual value. But perl consider all these internals as something which is not your business. For you, scalar represents a value. So if you pass it to SendMessage it will try convert this value to lParam (which is actually long). Since the scalar is empty, the result of conversion will be 0, and this value will be send as pointer to buffer in which the contents of edit control will be stored. The result of SendMessage will be an attempt to write in address 0, which is rarely the thing you want.

So what shall we do? Shall we use reference to $buffer? No - it will not help, since references are like scalars - perl make them look like references, but behind the scenes there are still some structures involved. What we need is the pointer to the memory where the actual scalar's value is stored. Perl is not very supportive in finding this, but it is possible. You get this pointer using unpack function.

Note however, that perl assumes that you do not deal with it's internals, so it does not do any attempt to assure that such a pointer points to something useful all the time. If for example, you append something to scalar, which will force memory reallocation, the previous pointer will start pointing to nowhere. But if you get this pointer just before the call to SendMessage, the pointer should remain valid. Let's try:

Example 2.3. Getting a contents of Edit control in perl (2nd attempt)


    use Win32::GuiTest qw( SendMessage );
    use strict;
    # WM_GETTEXT is 0xD
    my $msg_id = 0xd;
    my $hwnd = 0x204ba;
    my $buffer = " " x 100;
    my $buf_ptr = pack( 'P', $buffer );
    my $ptr = unpack( 'L!', $buf_ptr );
    SendMessage( $hwnd, $msg_id, 100, $ptr ); 
    print "The result from Calculator is $buffer\n";

This time it worked.

Armed with this knowledge we can immediately jump to dealing with more sophisticated controls like ListView. Note: If you are familiar a little bit with dealing with advanced MS controls, you may consider following code snippets artificial. I will refer to some structures and I will ignore the fact that Microsoft provides some macros which simplifies sending messages. I am doing this only for educational purposes. I am using ListView as good example to illustrate controls internals.

Example of a ListView control is given below

As you see it is a commonly used control. Let's try to get a first item from such a list. If you look in the MSDN documentation you will find that in order to get an a text of an item from the list you have to send it a message LVM_GETITEMTEXT. This is what MSDN says about this message:

As you can see, wParam should be equal to an index of an item to be retrieved. lParam should point to a memory used for data interchange. However, ListView do not use plain character buffer. It uses LVITEM structure instead. LVITEM looks like this:

Not all members have to be populated when getting an item text. One of the fields, which have to populated is pszText. It should be a pointer to a memory, to which an item text will be copied.

How can you use C structures in perl? pack function comes to the rescue here. In order to get a better understanding of pack/unpack functions, read perlpacktut manual page. In short it works this way: physically, C structure is string of bytes. Structure is a notion provided by C, which helps humans to deal with data having several attributes. So if we want to populate a memory in a way that it looks exactly as if a particular C structure is placed there, we have to put contents of all structure's fields in this memory. You can refer to pack documentation, or simply trust me that the code below really sends a structure to a control.

Example 2.4. Getting a a text of an item in ListView control in perl

    use Win32::GuiTest qw( :ALL );
    use strict;
    my $hwnd = 0x804ae;
    my $lvitem = "";
    my $item_text = " " x 100;

    $lvitem = pack( "L L L L L L L L L L", 
        0, #mask
        0, #iItem
        0, #iSubItem
        0, #state
        0, #stateMask
        unpack( 'L!', pack( 'P', $item_text ) ), #pszText
        100, #cchTextMax
        0, #iImage
        0, #lParam
        0, #iIndent
    );
    # LVM_GETITEMTEXT is 0x1000 + 45
    SendMessage( $hwnd, 0x1000 + 45, 0, unpack( 'L!', pack( 'P', $lvitem ) ) );
    print "List view item text is $item_text\n";

If you run it and if you are lucky enough, the application which hosts the list view control will crash immediately. If not, you still have good chances that something really bad has happened. But the nature of this problem is different from the problem with Edit control described earlier. If you look at SendMessage documentation you will read that for messages with id below WM_USER (which is 1024) Win32 will do a marshalling. For other messages you have to take care of it yourself. What is marshalling? Marshalling means sending data between processes. Not only bytes, but also objects, structures. Marshalling is not a technique. It is a notion of sending data. As we already know, SendMessage often expects lParam to be a pointer. But physically, lParam is only a long number. If you allocate a memory in process A, allocating function will return you the pointer to this memory in the address space of the calling process (i.e. process A). That's really important to understand. Remember that in Win32 there is no such thing like a global, universal memory addressing method, which would allow process to refer to any place of physical memory (or at least this mechanism is not promptly provided - I don't know. Waiting for your feedback). Each pointer is valid only in address space of one process. So if process A calls SendMessage on window owned by process B and pass a pointer to a memory, this pointer will not be valid in the address space of a process B, which hosts ListView or any other control. OK, so why our first example worked? Because WM_GETTEXT is below 1024. So Win32 did the marshalling itself.

Unfortunately, LVM_GETITEMTEXT, which returns an item from ListView is above WM_USER (1024). So we have to do marshalling ourselves. There are probably many ways of doing this but the most common are the following:

  • DLL injection using Win32 hooks

  • Allocation of memory in other processes address spaces

DLL injection using Win32 hooks allows you to intercept calls to some functions in other process and call functions in our process's address space instead. The good coverage of this topic can be found in "Programming Applications for Microsoft Windows, 4th edition" by Jeffrey Richter, chapter 22 "DLL Injection and API Hooking". It is already used in Win32::GuiTest. And it works well. The only disadvantage it has is that if you want to be able to send new messages, you have to make changes in Win32::GuiTest guts and recompile it. So it is not particularly good for experimenting with new controls.

The method I am going to present is based on some interesting mechanism provided by Win32: you can allocate memory in other process address space. Look at the code below:

Example 2.5. Getting a a text of an item in ListView control in C

    #include <windows.h>
    #include <commctrl.h>
    #include <stdio.h>

    int main(int argc, char* argv[])
    {
    
        HWND hWnd = HWND( 0x703F4 );
    
        LVITEM lvitem;
        char buffer[ 200 ];
    
        DWORD pid = 0;
        GetWindowThreadProcessId( hWnd, &pid );
        HANDLE hProcHnd = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
        LPVOID pLVI = VirtualAllocEx( hProcHnd, NULL, sizeof( LVITEM ), 
                       MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
        LPVOID pBuffer = VirtualAllocEx( hProcHnd, NULL, 200, 
                       MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    
        lvitem.mask = 0;
        lvitem.iItem = 0;
        lvitem.iSubItem = 0;
        lvitem.state = 0;
        lvitem.stateMask = 0;
        lvitem.pszText = ( char *)pBuffer;
        lvitem.cchTextMax = 200;
        lvitem.iImage = 0;
        lvitem.lParam = 0;
        lvitem.iIndent = 0;
        DWORD copied = 0;
        WriteProcessMemory( hProcHnd, pLVI, &lvitem, sizeof( LVITEM ), &copied );
        SendMessage( hWnd, LVM_GETITEMTEXT, (WPARAM)0, (LPARAM)pLVI );
        ReadProcessMemory( hProcHnd, pBuffer, (LPVOID)buffer, 200, &copied );
        VirtualFreeEx( hProcHnd, pBuffer, 0, MEM_RELEASE );
        VirtualFreeEx( hProcHnd, pLVI, 0, MEM_RELEASE );
        printf( "The item is %s\n", buffer );
        return 0;
    }

This time it worked.

Let me now explain the program step by step. Firstly we call GetWindowThreadProcessId. It returns a thread id and a process id which owns the window pointed by hWnd. We don't care about the thread id, but we will need process id. In order to manipulate other process's memory, we need a handle to this process. We get a handle to a process by calling OpenProcess and passing process id as a parameter. Then we can start allocating memory. We do it calling VirtualAllocEx. We do it twice - once for LVITEM structure, and second time for the buffer to which a control will copy the item's text. Then we populate a local copy of LVITEM structure with the correct values and we copy it to other process's address space, calling WriteProcessMemory. We are now ready to call SendMessage. We do it, passing it 0 as wParam (first element from the list) and pLVI as a lParam. pLVI is a pointer returned by VirtualAllocEx. This pointer is invalid in address space of process which calls VirtualAllocEx. But it is valid in the address space of the process which hosts the control we interact with. And this is what we want. Fine, but if we can't use the pointer in the calling process, how do we exchange data. How would we access from our process the data returned by the control? Well, we have done this already. ReadProcessMemory and WriteProcessMemory are functions, which allow us to copy data from other process address space to ours and vice versa. Once everything is done, we are good citizens and we free the allocated memory.

And now the equivalent perl code:

Example 2.6. Getting a contents of list view in perl

    use Win32::GuiTest qw( :ALL );
    use strict;

    my $hwnd = 0x10326; 
    my $lvitem = AllocateVirtualBuffer( $hwnd, 200 );
    my $text_buf = AllocateVirtualBuffer( $hwnd, 200 );
    my $str_buf = pack( "L L L L L L L L L L", 
        0, #mask
        0, #iItem
        0, #iSubItem
        0, #state
        0, #stateMask
        $text_buf->{ 'ptr' }, #pszText
        200, #cchTextMax
        0, #iImage
        0, #lParam
        0, #iIndent );

    WriteToVirtualBuffer( $lvitem, $str_buf );
    #LVM_GETITEMTEXT = 0x1000 + 45
    SendMessage( $hwnd, 0x1000 + 45, 0, $lvitem->{ 'ptr' } );
    my $value = ReadFromVirtualBuffer( $text_buf, 200 );
    $value =~ s/^(\w+)(.*)/$1/;
    FreeVirtualBuffer( $lvitem );
    FreeVirtualBuffer( $text_buf );
    print "The item is $value\n";

This code definitely needs some further explanations. There are few new functions used:

Note: As for now this functions are not a part of a standard distribution. If you are interested in using them, you can get the ppm package from here.

AllocateVirtualBuffer allocates the memory in the address space of a process, which owns the window pointed by handle $hwnd. It returns a reference to a hash, which contains 2 elements: 'process' being a process handle, returned by OpenProcess, and 'ptr', which is an actual pointer to a memory in other process's address space. Then we populate $str_buf string with bytes so it looks in memory exactly like LVITEM structure. Then we copy those bytes to other process's address space (by calling WriteToVirtualBuffer). Then we call SendMessage. And we get the returned data using ReadFromVirtualBuffer function. After we are done, we have to free allocated memory. And this is what is FreeVirtualBuffer function for.

Summary

Phew... that what was tough. Don't be frustrated if you did not get it after the first reading. Just read it again, and even better, try to run included example code.

One of the first questions you may ask, after reading this, would be: why should I bother using this if there are already Win32::GuiTest functions for manipulating List View? The answer is: you shouldn't. Existing Win32::GuiTest functions work pretty well, so there is no need to reinvent the wheel. I used List View in my example, because it is commonly available control, so any one can experiment with this.

You should consider using the method described above if you would like to send some less common messages to common controls. Or if you have a control from a third party (like winwidgets for example).

Chapter 3. Win32::GuiTest functions overview

This chapter should give you an overview of what kind functions you may expect to find in Win32::GuiTest. You can find details on each group of functions in consecutive chapters. You can also find detailed description of each function in alphabetical list.

Functions can be divided on the following four groups:

  • Windowing, identification and general purpose functions - functions from these groups are used for finding window handles, setting and getting common properties of windows and others

  • Controls related functions - functions from these group are used for manipulating controls - common and custom ones

  • Mouse and screen functions - functions from these group allow you to simulate mouse events and query properties of the current display

  • Keyboard functions

  • Menu functions

Chapter 4. Windowing, identification and general purpose functions

Functions described in this chapter are used for changing and querying attributes which are common to most of windows. Examples of such attributes are window handles, window coordinates etc.

Finding windows/windows handle

In order to do anything to any window you have to know it is window handle. Window handle is an integer number, which uniquely identifies a window in a system. If you have a look at Windows API you will notice, that most of functions operating on windows, require window handle of a window they are about to operate. The are 2 functions for finding windows handle in Win32::GuiTest:

FindWindowLike

Finds the window handles of windows matching the specified parameters and them as a list.

WaitWindowLike

Works very much like FindWindowLike. Waits for a particular window until timeout is reached.

WaitWindow

Minimal version of WaitWindowLike. Only requires the window title regexp. You can also specify the wait timeout in seconds.

General windowing functions

Functions in this section apply to virtually every window

GetActiveWindow

Returns an active window attached to a thread, which created a window identified by function's input parameter

GetChildDepth

Returns a number of levels in the windows' hierarchy tree between 2 windows.

GetChildWindows

Returns window handles of all windows, which are children (direct or indirect i.e. grand-children, grand-grand-children etc) of a window with a handle given as an input parameter.

GetClassName

Retrieves the name of the class to which the specified window belongs.

GetDesktopWindow

Returns a handle to the desktop window. The desktop window covers the entire screen. The desktop window is the area on top of which other windows are painted.

GetForegroundWindow

Returns a handle to the foreground window (the window with which the user is currently working)

GetParent

Returns a handle to the specified window's parent or owner.

GetWindow

Retrieves a handle to a window that has the specified relationship (Z-Order or owner) to the specified window.

GetWindowID

Returns the control Id of the specified window.

GetWindowLong

Retrieves information about the specified window. This is a simple wrapper around Win32 function.

GetWindowRect

Retrieves the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.

GetWindowText

Retrieves the text of the specified window's title bar (if it has one). If the specified window is a control, the text of the control is retrieved.

IsChild

Tests whether a window is a child window or descendant window of a specified parent window.

IsWindow

Tests whether the specified window handle identifies an existing window.

IsWindowEnabled

The IsWindowEnabled function determines whether the specified window is enabled for mouse and keyboard input.

IsWindowStyle

The IsWindowStyle function determines whether the specified window has a particular window style.

IsWindowStyleEx

The IsWindowStyleEx function determines whether the specified window has a particular extended window style.

IsWindowVisible

The IsWindowVisible function retrieves the visibility state of the specified window.

PostMessage

Posts a message to a given window.

SendMessage

Sends a message to a given window.

SetActiveWindow

Activates a window.

SetFocus

The SetFocus function sets the keyboard focus to the specified window

SetForegroundWindow

The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user.

SetWindowPos

The SetWindowPos function changes the size, position, and Z order of a child, pop-up, or top-level window.

ShowWindow

Set's the specified window's show state.

Process related functions

Funtions in this section are helpful when dealing with process related issues

AllocateVirtualBuffer

Allocates memory in the address space of a process, which is an owner of a given window.

FreeVirtualBuffer

Frees memory allocated by AllocateVirtualBuffer.

ReadFromVirtualBuffer

Reads from memory allocated by AllocateVirtualBuffer.

WaitForReady

Waits until the application is ready to receive more input

WriteToVirtualBuffer

Writes to memory allocated by AllocateVirtualBuffer.

Chapter 5. Controls related functions

This chapter describes functions used for manipulating several types of controls

This chapter is organized control-wise, since in most cases you will have a control and then you will look in the documentation in order to find out what can you do about them/how can you do what you want

In general you can classify all controls in 2 groups:

  • Common controls - they are provided by Microsoft for a long time and you may think of them as a part of operating system. The most important thing is that SendMessage handles all the necessary marshalling for you (don't worry if it does not tell you anything. I will explain it later)

  • Advanced controls and controls provided by other vendors - these are provided by Microsoft and other vendors. The most important differentiator between these and common controls is this marshalling thing

So what is marshalling all about?

In order to understand the issue, you need some background. Don't worry it won't hurt :), even if you are not an experienced Win32 programmer.

The most common mean of communicating with windows (i.e. controls, since they are windows, too) is by messages. If you want to add an item to a list control, you have to send it a message saying "please add this item to your list". To be more specific, you do it by calling SendMessage function. It has 4 parameters. First one is a handle to a window you want to communicate. Second one is message id - a command you want to send (add an item to a list) and the third and fourth one should contain additional parameters like a pointer to an item (string). The problem is, that if you issue this command from a script, which tests the application hosting this control, you are actually making interprocess call (script is one process, tested application - another one). The pointer to an item is valid only in address space of the test script. It will be invalid pointer in address space of tested application. This is where marshalling comes to the rescue. Marshalling is a trick (there are few kinds of tricks) which allows processes to exchange pointers and data. For common controls, Win32 do marshalling for you. It checks the command parameter in SendMessage and if it recognizes a command related to one of its basic controls, it does the marshalling for you. If you deal with other controls (not common) you have to take care about marshalling yourself. For more detailed description on what is marshalling and how it affects the code see the advanced tutorial.

There are 3 ways (which I know) of doing marshalling:

  • API hooking - you may intercept calls to some functions and make other process to call your function, in its address space (am I right? I have to double check)

  • DLL injection - you may force other process to run a dll provided by you in its address space

  • Using VirtualAllocEx function - this function allows to allocate memory in other process address space. You can send a pointer returned by VirtualAllocEx to this process and it will be able to safely use it

Currently in Win32::GuiTest marshalling for custom controls is done by API hooking. Although it works, I believe using VirtualAllocEx related method provides bigger flexibility. Have a look at the advanced tutorial to see VirtualAllocEx at work.

General controls related functions

This sections contains functions, which perform operations common for controls

EnableWindow

Enables or disables mouse and keyboard input to the specified window or control.

GetCaretPos

Returns the caret's position in client coordinates.

GetFocus

Retrieves the handle to the window that has the keyboard focus and is attached to a thread, which owns window specified as an input parameter

WMGetText

Retrieves the text associated with the control (for example edited text from EditBox)

WMSetText

Sets the text associated with the control (for example edited text in EditBox)

Common controls

The following controls are considered a common controls:

  • Buttons (WNDCLASS - "BUTTON", MFC Class - CButton) - Represent a button which you can push/check by clicking/using keyboard

  • List boxes (WNDCLASS - "LISTBOX", MFC Class - CListBox) - Represents a list of items, which can be selected by mouse or keyboard

  • Edit controls (WNDCLASS - "EDIT", MFC Class - CEdit) - Represents an input box in which you can insert and edit text

  • Combo boxes (WNDCLASS - "COMBOBOX", MFC Class - CComboBox) - Represents a control which is a list, but in the same time allows you to type and edit your own values

  • Scroll bars (WNDCLASS - "SCROLLBAR", MFC Class - CScrollBar) - Vertical or horizontal bar which is helpful for scrolling contents in windows.

  • Static controls (WNDCLASS - "STATIC", MFC Class - CStatic) - Represents a static label

Buttons

Buttons are controls, which is most cases are used in the following ways:

  • As push buttons - a button on a window or dialog box, which can be pushed by mouse or by using keyboard. Pushing the button will trigger some action. NOTE: Although buttons from toolbars (like in MS Word) have the same functionality, there is a quite different handling behind the scenes. What you find in this section applies to standalone push buttons, not buttons in the toolbar.

  • As radio buttons - a group of buttons, from which only one can be selected in a moment

  • As checkbox - A small square, which can be checked or unchecked

  • As group box - used for printing frames around a group of other controls

Win32::GuiTest provides the following functions for dealing with buttons:

CheckButton

Sends a BM_SETCHECK message to set the check state of a radio button or check box.

IsCheckedButton

Retrieves the state of the button. Returns TRUE if button checked, FALSE otherwise.

IsGrayedButton

Retrieves the state of the button. Returns TRUE if button grayed, FALSE otherwise.

PushButton

Pushes a button on the foreground window. Equivalent to PushChildButton( GetForegroundWindow(), $button, $delay ).

PushChildButton

Allows generating a mouse click on a particular button.

PushChildById

Allows generating a mouse click on a particular button. Only control id can be given as parameter.

List boxes

List boxes are controls which allows you to chose item from the list.

Win32::GuiTest provides the following functions for dealing with list boxes:

GetListContents

Returns a list of all items stored in the list box.

GetListText

Returns an item, which has a given ordinal number

Combo boxes

Combo boxes are controls which combine the features of list box and edit field. They allow choosing items from the list but in the same time they allow editing.

Win32::GuiTest provides the following functions for dealing with combo boxes:

GetComboContents

Returns a list of all items stored in the ComboBox.

GetComboText

Returns an item, which has a given ordinal number

SelComboItem

Select a string in the list of a combo box based off an index (zero-based).

SelComboItemText

Selects an item in the combo box based off text (case insensitive). Does not make combo box to send CBN_SELCHANGE notification.

SelComboString

Selects an item in the combo box based off text (case insensitive). Makes combo box to send CBN_SELCHANGE notification.

Other controls

All controls, which are not common are described in this section.

Microsoft's tab controls

GetTabItems

Returns a list of a tab control's labels.

IsTabItemSel

Determines if the specified tab item is selected.

SelectTabItem

Sets the focus to a specified tab in a tab control

SelTabItem

Selects a tab based off an index (zero-based).

SelTabItemText

Selects a tab based off text label (case insensitive).

TabCtrl_GetCurFocus

Returns the index of the item that has the focus in a tab control.

TabCtrl_GetItemCount

Retrieves the number of tabs in the tab control.

TabCtrl_SetCurFocus

Sets the focus to a specified tab in a tab control.

TabCtrl_SetCurSel

Selects a tab in a tab control.

Microsoft's List-View controls

A list-view control is a window that displays a collection of items; each item consists of an icon and a label. List-view controls provide several ways to arrange and display items. For example, additional information about each item can be displayed in columns to the right of the icon and label.

GetListViewContents

Returns a list of texts of the specified list view.

IsListViewItemSel

Determines if the specified list view item is selected.

SelListViewItem

Selects an item in the list view based off an index (zero-based).

SelListViewItemText

Selects an item in the list view based off text (case insensitive).

Microsoft's Tree-View controls

A tree-view control is a window that displays a hierarchical list of items, such as the headings in a document, the entries in an index, or the files and directories on a disk. Each item consists of a label and an optional bitmapped image, and each item can have a list of subitems associated with it. By clicking an item, the user can expand or collapse the associated list of subitems.

GetTreeViewSelPath

Returns a string containing the path (i.e., "parent|child") of the currently selected tree view item.

SelTreeViewItemPath

Selects a tree view item based off a "path" (case insensitive).

Chapter 6. Mouse and screen functions

This chapter describes function related to mouse and screen. Most of mouse operations require that you give screen coordinates so I decided to describe screen and mouse functions together.

ClientToScreen

Converts the client-area coordinates of a specified point to screen coordinates.

GetCursorPos

Retrieves the cursor's position, in screen coordinates.

GetScreenRes

Retrieves a height and width of a screen in pixels.

MouseClick

Allows one to easily interact with an application through mouse emulation.

MouseMoveAbsPix

Move the mouse cursor to given coordinates. Coordinates are are calculated against top-left corner of the screen (0,0) and are given in pixels.

MouseMoveWheel

Emulate mouse wheel movement.

NormToScreen

Converts normalized coordinates to coordinates in pixels.

ScreenToClient

Converts the screen coordinates of a specified point on the screen to client-area coordinates

ScreenToNorm

Returns normalized coordinates of given point (0-FFFF as a fraction of screen resolution)

SendLButtonDown

Simulates that the left mouse button is down in the current location of mouse pointer.

SendLButtonUp

Simulates that the left mouse button is up in the current location of mouse pointer.

SendMButtonDown

Simulates that the middle mouse button is down in the current location of mouse pointer.

SendLButtonUp

Simulates that the middle mouse button is up in the current location of mouse pointer.

SendMouse

Emulates mouse input.

SendMouseMoveRel

Moves a mouse cursor on the screen. Coordinates are relative to the last reported (current) position.

SendMouseMoveAbs

Moves a mouse cursor on the screen. Coordinates are relative to the upper left corner of the screen i.e. are absolute.

SendRButtonDown

Simulates that the right mouse button is down in the current location of mouse pointer.

SendRButtonUp

Simulates that the right mouse button is up in the current location of mouse pointer.

WindowFromPoint

Retrieves a handle to the window that contains the specified point.

Chapter 7. Keyboard functions

This section describes functions related to keyboard.

IsKeyPressed

Checks if the user pressed the specified key.

SendKeys

Sends keystrokes to the active window as if typed at the keyboard using the optional delay between keystrokes

SendRawKey

Wrapper around keybd_event. Allows sending low-level keys.

Chapter 8. Menu functions

This section describes functions related to Menu.

GetMenu

Returns MenuID.

GetMenuItemCount

Determines the number of items in the specified menu.

GetMenuItemIndex

Returns the index of the menu item (-1 if not found)

GetMenuItemInfo

Retrieves information about a menu item.

GetPopupHandle

Opens popup menu and returns menu id (menu handle) for it.

GetSubMenu

Retrieves a handle to the drop-down menu or submenu activated by the specified menu item.

GetSystemMenu

Allows the application to access the window menu (also known as the system menu or the control menu) for copying and modifying.

MenuSelect

Allows selecting menu programmatically

Chapter 9. Appendix - functions in alphabetical order

AllocateVirtualBuffer

Allocates memory in the address space of a process, which is an owner of a given window, identified by $hwnd. Returns a hash which has 2 elements:

Syntax

$buf_str = AllocateVirtualBuffer( $hwnd, $size );

Parameters

$hwnd

Handle of any window owned by a process, in which address space we want to allocate memory

$size

Size (in bytes) of memory we want to allocate

Return value

Function returns a reference to a hash with following elements:

ptr

Address of the allocated memory (in the other process address space)

process

process handle (in the Win32 meaning, as returned by Win32 OpenProcess API function

Remarks

In order to understand what is this function for, have a look at advanced tutorial.

CheckButton

Sends a BM_SETCHECK message to set the check state of a radio button or check box.

Syntax

CheckButton( $hwnd );

Parameters

$hwnd

Window handle of a button which the function should set to "checked" state

ClientToScreen

The ClientToScreen function converts the client-area coordinates of a specified point to screen coordinates. It is a simple wrapper around Win32 ClientToScreen.

Syntax

( $sx, $sy ) = ClientToScreen( $hwnd, $cx, $cy );

Parameters

$hwnd

Handle of a window hosting a client area

$cx

x coordinate in client area

$cy

y coordinate in client area

Return value

$sx

Converted x coordinate

$sy

Converted y coordinate

EnableWindow

The EnableWindow function enables or disables mouse and keyboard input to the specified window or control. When input is disabled, the window does not receive input such as mouse clicks and key presses. When input is enabled, the window receives all input. It is a simple wrapper around Win32 EnableWindow

Syntax

( $result ) = EnableWindow( $hwnd, $fEnable );

Parameters

$hwnd

Handle of a window to be enabled

$fEnable

Specifies whether window should enabled or disabled

Return value

TO BE DONE

FindWindowLike

Finds the window handles of the windows matching the specified parameters and returns them as a list. You may specify the handle of the window to search under. The routine searches through all of this windows children and their children recursively. If 'undef' given, then the routine searches through all windows. There is also a regexp used to match against the text in the window caption and another regexp used to match against the text in the window class. If you pass a child ID number, the functions will only match windows with this id. In each case 'undef' matches everything.

Syntax

@hwnd = FindWindowLike( $parent, $titleregex, $classregex, $childid, $maxlevel );

Parameters

$parent

Handle of a window, which children we are looking for. If undefined, handle of the desktop is assumed

$titleregex

Regular expression used to match windows' caption. If not undef, only windows, which have caption matching with $titleregex will be returned. If undef, windows' caption is not considered during search

$classregex

Same as $titleregex but applies to window's class name

$childid

Control id of a child/children to be returned. If undef, $childid is not taken into consideration

$maxlevel

Maximum level in the window hierarchy tree for which child windows will be searched. Level 2 means that only direct children of $parent will be searched (which IMHO is misleading and should be changed)

Example 9.1. Getting all windows (apart from desktop)

    @hwnds = FindWindowLike();                            
    

Example 9.2. Finding calculator window

    @hwnds = FindWindowLike( undef, "^Calculator" );                            
    

Example 9.3. Finding a button of id=123, which is a direct child of the $parent

    @hwnds = FindWindowLike( $parent, undef, "Button", 123, 2 );                            
    

FreeVirtualBuffer

Frees memory allocated in the address space of different process by AllocateVirtualBuffer.

Syntax

FreeVirtualBuffer( $buf_str );

Parameters

$buf_str

Reference to a hash returned by AllocateVirtualBuffer

Remarks

In order to understand what is this function for, have a look at advanced tutorial.

GetActiveWindow

Returns an active window attached to a thread, which created a window identified by function's input parameter $hwnd.

Syntax

$hwnd = GetActiveWindow( $hwnd );

Parameters

$hwnd

- A window handle of any of windows belonging to a thread for which we want to find active window

Return value

A handle to an active window

Remarks

It is a wrapper around Win32 GetActiveWindow, however not a simple one. Win32 GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue. Win32::GuiTest GetActiveWindow returns an active window attached to a thread, which created a window identified by function's input parameter. So if an application has 10 windows opened, and we would like to know, which is the active one, we call GetActiveWindow giving it a handle of any application's windows.

GetCaretPos

The GetCaretPos function returns the caret's position in client coordinates. It is a simple wrapper around Win32 GetCaretPos

Syntax

( $cx, cy ) = GetCaretPos( $hwnd );

Parameters

$hwnd

Handle of a window in which the caret is placed

Return value

$cx

x coordinate of a caret

$cy

y coordinate of a caret

GetChildDepth

Returns a number of levels in the windows' hierarchy tree between the $ancestor and $child. NOTE: For direct children functions returns 2, which I don't think is correct. This problem exists for all levels. The result is always increased by one.

Syntax

$depth = GetChildDepth( $ancestor, $child );

Parameters

$ancestor

A window handle to ancestor

$child

A window handle to child

Return value

Number of levels in the windows' hierarchy tree between the $ancestor and $child. NOTE: For direct children functions returns 2, which I don't think is correct. This problem exists for all levels. The result is always increased by one.

GetChildWindows

GetChildWindows returns window handles of all windows, which are children (direct or indirect i.e. grand-children, grand-grand-children etc) of a window with a handle given as an input parameter.

Syntax

@hwnds = GetChildWindows( $hwnd );

Parameters

$hwnd

A handle of a window, for which we are looking for children

Return value

A list of all child windows

GetClassName

The GetClassName function retrieves the name of the class to which the specified window belongs. It is a simple wrapper around Win32 GetClassName

Syntax

$class_name = GetClassName( $hwnd );

Parameters

$hwnd

A handle of a queried window

Return value

Name of a class of the queried window

GetComboContents

Returns a list of all items stored in a ComboBox.

Syntax

@items = GetComboContents( $hwnd );

Parameters

$hwnd

Window handle of a ComboBox

Return value

A list of all items stored in ComboBox

GetComboText

Returns an item, which has a given ordinal number

Syntax

$item = GetComboText( $hwnd, $index );

Parameters

$hwnd

Window handle of a ComboBox

$index

Index of an item to be returned (which items from the list)

Return value

Returned item

GetCursorPos

GetCursorPos function retrieves the cursor's position, in screen coordinates. It is a simple wrapper around Win32 function

Syntax

( $sx, $sy ) = GetCursorPos();

Return value

$sx

x cursor's coordinate

$sy

y cursor's coordinate

GetDesktopWindow

GetDesktopWindow function returns a handle to the desktop window. The desktop window covers the entire screen. The desktop window is the area on top of which other windows are painted. It is a simple wrapper around Win32 function.

Syntax

$hwnd = GetDesktopWindow();

Return value

Window handle of a desktop window

GetFocus

GetFocus function retrieves the handle to the window that has the keyboard focus and is attached to a thread, which owns window specified by $hwnd. So if an application has 10 windows opened, and we would like to know, which one has an input focus, we call GetFocus giving it a handle of any application's windows.

Syntax

$fc_hwnd = GetFocus( $hwnd );

Parameters

$hwnd

Handle of a window owned by a a thread of an application we are checking

Return value

A handle of a window, which has an input focus

GetForegroundWindow

GetForegroundWindow function returns a handle to the foreground window (the window with which the user is currently working).

Syntax

$hwnd = GetForegroundWindow();

Return value

Handle of window being in foreground.

Remarks

The system assigns a slightly higher priority to the thread that creates the foreground window than it does to other threads. This is a simple wrapper around Win32 function.

GetListContents

Returns a list of all items stored in the List.

Syntax

@items = GetListContents( $hwnd );

Parameters

$hwnd

Window handle of a list box

Return value

A list of all items stored in the list.

GetListText

Returns an item, which has a given ordinal number

Syntax

$item = GetListText( $hwnd, $index );

Parameters

$hwnd

Window handle of a list box

$index

Index of an item to be returned (which items from the list)

Return value

Found item

GetListViewContents

Returns a list of texts of the specified list view.

Syntax

@items = GetListViewContents( $hwnd );

Parameters

$hwnd

Window handle of a list view

Return value

Each element in the returned list is a reference to a list, which contains all fields in one row.

GetMenu

GetMenu function retrieves a handle to the menu assigned to the specified window. This is a simple wrapper around Win32 function.

Syntax

$menu_id = GetMenu( $hwnd );

Parameters

$hwnd

Handle of a window having a menu

Return value

Menu handle

GetMenuItemCount

GetMenuItemCount function determines the number of items in the specified menu. This is a simple wrapper around Win32 function.

Syntax

$mcount = GetMenuItemCount( $hmenu );

Parameters

$hmenu

Handle to the menu to be examined

Return value

Number of items in the menu

GetMenuItemIndex

Returns the index of the menu item (-1 if not found).

Syntax

$menu_idx = GetMenuItemIndex( $curr, $menu );

Parameters

$curr

Menu Id

$menu

(Localized !) name of the menu including the hot key: "Rep&eate"

Return value

Index of a found menu item

GetMenuItemInfo

GetMenuItemInfo function retrieves information about a menu item. Receives a menu handler (one we got from GetMenu or GetSubMenu) and a number (which is the location of the item within the given menu).

Syntax

%info = GetMenuItemInfo( $hmenu, $cnt );

Parameters

$hmenu

Handle to menu

$cnt

Position of the menu item to get information about

Return value

A hash in which there are currently 2 keys: type can be either "string" or "separator" - this is the type of the menu item text is the visible text of the menu item (provided only for "string" type) (TO DO: this description is not particularly clear)

Remarks

Receives a menu handler (one we got from GetMenu or GetSubMenu) and a number (which is the location of the item within the given menu).

GetParent

GetParent function retrieves a handle to the specified window's parent or owner. This is a simple wrapper around Win32 function.

Syntax

$par_hwnd = GetParent( $hwnd );

Parameters

$hwnd

Handle of a window whose parent window is to be retrieved

Return value

Handle to a parent window

GetPopupHandle

This function opens and gets the handle of a popup window generated by right-clicking at the $x and $y screen coordinates (absolute)

Syntax

$hpopup = GetPopupHandle( $hwnd, $x, $y, [$wait] );

Parameters

$hwnd

Handle of a window having a popup menu

$x

X coordinate of the right click

$y

Y coordinate of the right click

$wait

Optional delay between click and querying the menu, to give the menu some time to be created. Default is 50ms.

Return value

Zero if no popup menu is found

GetScreenRes

GetScreenRes function retrieves a height and width of a screen in pixels.

Syntax

( $wx, $wy ) = GetScreenRes();

Return value

Height and width of the screen in pixels

GetSubMenu

GetSubMenu function retrieves a handle to the drop-down menu or submenu activated by the specified menu item.

Syntax

$hsubmenu = GetSubMenu( $hmenu, $npos );

Parameters

$hmenu

Handle to the menu

$npos

Zero-based relative position in the specified menu of an item that activates a drop-down menu or submenu

Return value

Menu handle of a submenu

GetSystemMenu

GetSystemMenu function allows the application to access the window menu (also known as the system menu or the control menu) for copying and modifying. It is a simple wrapper around Win32 function.

Syntax

$hmenu = GetSystemMenu( $hwnd, $bRevert );

Parameters

$hwnd

Handle to the window that will own a copy of the window menu.

$bRevert

Specifies the action to be taken. If this parameter is FALSE, GetSystemMenu returns a handle to the copy of the window menu currently in use. The copy is initially identical to the window menu, but it can be modified. If this parameter is TRUE, GetSystemMenu resets the window menu back to the default state. The previous window menu, if any, is destroyed.

Return value

Menu handle

GetTabItems

Returns a list of a tab control's labels.

Syntax

@labels = GetTabItems( $hwnd );

Parameters

$hwnd

Handle to the tab control window

Return value

List of tab control's labels

GetTreeViewSelPath

Returns a string containing the path (i.e., "parent|child") of the currently selected tree view item.

Syntax

$path = GetTreeViewSelPath( $hwnd );

Parameters

$hwnd

Handle to the tree view control window

Return value

String containing a path to the currently selected item

Example 9.4. Getting a path

    $oldpath = GetTreeViewSelPath($window);
    SelTreeViewItemPath($window, "Parent|Child");
    SelTreeViewItemPath($window, $oldpath);

GetWindow

GetWindow function retrieves a handle to a window that has the specified relationship (Z-Order or owner) to the specified window. This is a simple wrapper around Win32 function.

Syntax

$hwnd = GetWindow( $hwnd, $uCmd );

Parameters

$hwnd

Handle to a window. The window handle retrieved is relative to this window, based on the value of the uCmd parameter.

$uCmd

Specifies the relationship between the specified window and the window whose handle is to be retrieved. There are quite a few possibilities. Check function's documentation on MSDN.

Return value

Handle to a found window

GetWindowID

GetWindowID function retrieves the control Id of the specified window.

Syntax

$ctrl_id = GetWindowID( $hwnd );

Parameters

$hwnd

Handle to a window for which control ID is to be retrieved.

Return value

Control id of a window

GetWindowLong

GetWindowLong function retrieves information about the specified window. This is a simple wrapper around Win32 function.

Syntax

$param = GetWindowLong( $hwnd, $index );

Parameters

$hwnd

Handle to a window for which information is to be retrieved.

$index

Specifies what kind of information is to be retrieved. There are many possibilities. Check MSDN for details.

Return value

Retrieved information

GetWindowRect

GetWindowRect function retrieves the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. This is a simple wrapper around Win32 function.

Syntax

( $lx, $ty, $rx, $by ) = GetWindowRect( $hwnd );

Parameters

$hwnd

Handle to a window for which information is to be retrieved.

Return value

Top left and bottom right screen coordinates of the rectangle

GetWindowText

GetWindowText function copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied. However, GetWindowText cannot retrieve the text of a control in another application.

Syntax

$text = GetWindowText( $hwnd );

Parameters

$hwnd

Handle to the window or control containing the text.

Return value

Returned window text

IsCheckedButton

Retrieves the state of the button. Returns TRUE if button checked, FALSE otherwise.

Syntax

$state = IsCheckedButton( $hwnd );

Parameters

$hwnd

Handle to the button to be queried.

Return value

Returns TRUE if button checked, FALSE otherwise.

Remarks

It sends BM_GETCHECK message to the button and compares return value of SendMessage with BST_CHECKED

IsChild

IsChild function tests whether a window is a child window or descendant window of a specified parent window. A child window is the direct descendant of a specified parent window if that parent window is in the chain of parent windows; the chain of parent windows leads from the original overlapped or pop-up window to the child window.

Syntax

$is_child = IsChild( $hwnd_parent, $hwnd );

Parameters

$hwnd_parent

Handle to the parent window.

$hwnd

Handle to the window to be tested

Return value

TRUE if the tested window is a child of $hwnd_parent, FALSE otherwise

IsGrayedButton

Retrieves the state of the button. Returns TRUE if button is grayed, FALSE otherwise.

NOTE: Grayed is not the same thing as disabled. Grayed has a meaning for radio buttons and checkboxes. To be more precise - it applies only if the button has the BS_3STATE or BS_AUTO3STATE style. Grayed means that its state is indeterminate. In order to check if the button is enabled, use IsWindowEnabled.

Syntax

$state = IsGrayedButton( $hwnd );

Parameters

$hwnd

Handle to the button to be queried.

Return value

Returns TRUE if button grayed, FALSE otherwise.

Remarks

It sends BM_GETCHECK message to the button and compares return value of SendMessage with BST_INDETERMINATE. Check MSDN for details.

IsKeyPressed

Wrapper around the GetAsyncKeyState Win32 function. Returns TRUE if the user presses the specified key.

Syntax

$is_pressed = IsKeyPressed( $key );

Parameters

$key

Key to be checked against

Return value

TRUE is the user presses the specified key

IsListViewItemSel

Determines if the specified list view item is selected.

Syntax

$is_sel = IsListViewItemSel( $hwnd, $txt );

Parameters

$hwnd

Control's window handle

$txt

Text, which should be contained by a selected list view item

Return value

TRUE if the specified item is selected. FALSE otherwise

IsTabItemSel

Determines if the specified tab item is selected.

Syntax

$result = IsTabItemSel( $hwnd, $txt );

Parameters

$hwnd

Control's window handle

$txt

Text in the tab, which is checked for being selected

Return value

TRUE if specified tab is selected. FALSE otherwise

IsWindow

The IsWindow function determines whether the specified window handle identifies an existing window. This is a simple wrapper around Win32 function.

Syntax

$is_window = IsWindow( $hwnd );

Parameters

$hwnd

Handle to be verified

Return value

TRUE is $hwnd identifies existing window. FALSE otherwise

IsWindowEnabled

The IsWindowEnabled function determines whether the specified window is enabled for mouse and keyboard input. This is a simple wrapper around Win32 function.

Syntax

$is_enableed = IsWindowEnabled( $hwnd );

Parameters

$hwnd

Handle of the window to be tested

Return value

TRUE if window is enabled, FALSE otherwise

IsWindowStyle

The IsWindowStyle function determines whether the specified window has a particular window style.

Syntax

$has_style = IsWindowStyle( $hwnd, $style );

Parameters

$hwnd

Handle of the window to be tested

$style

Style to be checked against. It has to be a numerical value. Currently no constants are defined so you have to find out proper values yourself (by greping windows header files)

Return value

TRUE if a window has a particular style, FALSE otherwise

IsWindowStyleEx

The IsWindowStyleEx function determines whether the specified window has a particular extended window style.

Syntax

$has_style = IsWindowStyleEx( $hwnd, $style );

Parameters

$hwnd

Handle of the window to be tested

$style

Extended style to be checked against

Return value

TRUE if a window has a particular style, FALSE otherwise

IsWindowVisible

The IsWindowVisible function retrieves the visibility state of the specified window.

Syntax

$is_visible = IsWindowVisible( $hwnd );

Parameters

$hwnd

Handle of the window to be tested

Return value

TRUE is a window is visible. FALSE otherwise

MenuSelect

Allows selecting menu programmatically.

Syntax

MenuSelect( $item, $hwnd, $menu );

Parameters

$item

Menu item to be selected

$hwnd

Handle of a window hosting a menu. If not given, foreground window is assumed.

$menu

Handle to a menu. If not given, the result of GetMenu( $hwnd ) is assumed

Example 9.5. Exit foreground application through application menu

    MenuSelect("&File|E&xit");

Example 9.6. Exit foreground application through system menu

    MenuSelect("&Close", 0, GetSystemMenu(GetForegroundWindow(), FALSE));

MouseClick

Allows one to easily interact with an application through mouse emulation.

Syntax

MouseClick( $window, $parent, $x_offset, $y_offset, $button, $delay );

Parameters

$window

Regexp for a Window caption/Child caption, or just a Child ID

$parent

Handle to parent window. Default is foreground window. Use GetDesktopWindow return value for this if clicking on an application title bar

$x_offset

Offset for X axis. Default is 0

$y_offset

Offset for Y axis. Default is 0

$button

{LEFT}, {MIDDLE}, {RIGHT}. Default is {LEFT}

$delay

Default is 0. 0.50 = 500 ms. Delay between button down and button up.

Example 9.7. Click on CE button if its parent window is in foreground

    MouseClick('^CE$');

Example 9.8. Right click on CE button if its parent window is in foreground

    MouseClick('^CE$', undef, undef, undef, '{RIGHT}');

Example 9.9. Click on 8 button window under the specified parent window

    MouseClick('8', $parent);

Example 9.10. Click on Calculator parent window itself

    MouseClick('Calculator', GetDesktopWindow());

MouseMoveAbsPix

Move the mouse cursor to given coordinates. Coordinates are are calculated against top-left corner of the screen (0,0) and are given in pixels.

Syntax

MouseMoveAbsPix( $x, $y );

Parameters

$x

x coordinate

$y

y coordinate

MouseMoveWheel

Emulate mouse wheel movement. It is wrapper around Win32 function mouse_event, using MOUSEEVENT_WHEEL flag.

Syntax

MouseMoveWheel( $change );

Parameters

$change

Positive or negative value (depending on direction) of mouse wheel movement

NormToScreen

Converts normalized coordinates to coordinates in pixels.

Syntax

( $px, $py ) = NormToScreen( $nx, $ny );

Parameters

$nx

Normalized x coordinate

$ny

Normalized y coordinate

Return value

Screen coordinates of the given point

PostMessage

The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message (which is opposite to SendMessage, which forces the thread to wait until the target window processes the message). DO NOT think of it as simple wrapper around Win32 function! The code itself simply wraps the original Win32 function but 3rd and 4th parameter of PostMessage have to be interpreted differently, depending on the message. Sometimes they are treated as longs, sometimes as pointers. Current implementation of Win32::GuiTest::PostMessage is not that smart so it is actually of a very limited use. It would be good to implement some smarter version of PostMessage

Syntax

$result = PostMessage( $hwnd, $msg, $wParam, $lParam );

Parameters

$hwnd

Handle of a window, to which a message is sent.

$msg

Message id

$wParam

Specifies additional message-specific information

$lParam

Specifies additional message-specific information

Return value

Value returned for a particular message

PushButton

Pushes a button on the foreground window. Equivalent to PushChildButton ( GetForegroundWindow(), $button, $delay ).

Syntax

$result = PushButton( $button, $delay );

Parameters

$button

Text or Control ID of the button

$delay

[Optional] the time (0.25 means 250 ms) to wait between the mouse down and the mouse up event

PushChildButton

Allows generating a mouse click on a particular button. Returns 1 if the button has been found. 0 otherwise. Function is looking for the button among all children of the $parent. Not only first level children are considered by also second level, third level and so on.

Syntax

$result = PushChildButton( $parent, $button, $delay );

Parameters

$parent

- The parent window of the button

$button

- Text or Control ID of the button

$delay

- [Optional] the time (0.25 means 250 ms) to wait between the mouse down and the mouse up event

Return value

What does it actually return????

Remarks

Be careful when using this function. Detailed explanation of potential problems can be found here

PushChildById

Allows generating a mouse click on a particular button.

Syntax

PushChildById( $parent, $button, $level, $delay );

Parameters

$parent

Handle to a window, which is an ancestor of a button to be pushed

$button

Control id of a button to be pushed

$level

How many levels in windows hierarchy is a button below ancestor given by $parent. Default value is 2, which means direct child

$delay

Time interval in miliseconds between pushing and releasing the button. Default value is 0.

Remarks

Allows pushing a button, which control id is eqaul to a $button. PushChildButton tries to match parameter against control id or caption, which may lead to some unexpected results. PushChildById matches only against control id. Secondly, PushChildById allows specifying search depth in the windows hierarchy tree. The default is 2, which means that only direct children will be pushed.

ReadFromVirtualBuffer

Reads from memory allocated in the address space of different process by AllocateVirtualBuffer.

Syntax

$str = ReadFromVirtualBuffer( $buf_str, $size );

Parameters

$buf_str

Reference to a hash returned by AllocateVirtualBuffer

$size

Number of bytes to be read

Return value

Function returns a string with data read from the virtual buffer

Remarks

In order to understand what is this function for, have a look at advanced tutorial.

ScreenToClient

The ScreenToClient function converts the screen coordinates of a specified point on the screen to client-area coordinates

Syntax

($cx,$cy) = ScreenToClient( $hwnd, $sx, $sy );

Parameters

$hwnd

Handle to the window whose client area will be used for the conversion

$sx

x screen coordinate to be converted

$sy

y screen coordinate to be converted

Return value

Client coordinates of a given point

ScreenToNorm

The ScreenToNorm function returns normalized coordinates of given point (0-FFFF as a fraction of screen resolution)

Syntax

( $nx, $ny) = ScreenToNorm( $sx, $sy );

Parameters

$sx

x screen coordinate to be converted

$sy

y screen coordinate to be converted

Return value

Normilized coordinates of a given point

SelComboItem

select a string in the list of a combo box based off an index (zero-based). If necessary, the list scrolls the string into view. The text in the edit control of the combo box changes to reflect the new selection, and any previous selection in the list is removed. This a simple wrapper around SendMessage using CB_SETCURSEL message.

Syntax

$result = SelComboItem( $hwnd, $item );

Parameters

$hwnd

Control's window handle

$item

Index (zero-based) of an item to be selected

Return value

Selected item

SelComboItemText

Selects an item in the combo box based off text (case insensitive). If necessary, the list scrolls the string into view. The text in the edit control of the combo box changes to reflect the new selection, and any previous selection in the list is removed. In contrary to SelComboString, after calling this function, combo box does not send CBN_SELCHANGE notification.

Syntax

$result = SelComboItemText( $hwnd, $text );

Parameters

$hwnd

Control's window handle

$text

Text in the item to be selected

Return value

Selected item

SelComboString

Selects an item in the combo box, which starts with a given string (case insensitive comaparison).

Syntax

SelComboString( $hwnd, $string, $start_idx );

Parameters

$hwnd

Handle to a combo box control

$string

String that contains the characters for which to search. The search is not case sensitive, so this string can contain any combination of uppercase and lowercase letters

$start_idx

Specifies the zero-based index of the item preceding the first item to be searched. When the search reaches the bottom of the list, it continues from the top of the list back to the item specified by the $start_idx parameter. If $start_idx is -1, the entire list is searched from the beginning.

Remarks

Search the list of a combo box for an item that begins with the characters in a specified string. If a matching item is found, it is selected and copied to the edit control. It is a wrapper around sending CB_SELECTSTRING message. In contrary to SelComboItemText this function causes combo box to send CBN_SELCHANGE notification.

Return value

Selected item

SelectTabItem

Sets the focus to a specified tab in a tab control

Syntax

$result = SelectTabItem( $window, $item, $parent );

Parameters

$window

Control's caption or Control ID

$item

Index of tab to get focus

$parent

Parent window. Default is foreground window

Return value

What does it actually return???

SelListViewItem

Selects an item in the list view based off an index (zero-based).

Syntax

$item = SelListViewItem( $hwnd, $idx, $multi_select );

Parameters

$hwnd

Control's window handle

$idx

Index (zero-based) of an item to be selected

$multi_select

[Optional] allows selecting multiple items

Return value

Text of a selected item

Example 9.11. Select first item, clears out any previous selections

    SelListViewItem( $win, 0 );

Example 9.12. Select an *additional* item

    SelListViewItem( $win, 1, 1 );

SelListViewItemText

Selects an item in the list view based off text (case insensitive).

Syntax

$item = SelListViewItemText( $hwnd, $txt, $multi_select );

Parameters

$hwnd

Control's window handle

$txt

Text to be searched in list view items

$multi_select

[Optional] allows selecting multiple items

Return value

Text of a selected item

Example 9.13. Select first item, clears out any previous selections

    SelListViewItemText( $win, 'Temp' );

Example 9.14. Select an *additional* item

    SelListViewItemText( $win, 'cabs', 1 );

SelTabItem

Selects a tab based off an index (zero-based).

Syntax

SelTabItem( $hwnd, $idx );

Parameters

$hwnd

Control's window handle

$idx

Index of tab to be selected

SelTabItemText

Selects a tab based off text label (case insensitive).

Syntax

SelTabItemText( $hwnd, $txt );

Parameters

$hwnd

Control's window handle

$txt

Text in the tab to be selected

SelTreeViewItemPath

Selects a tree view item based off a "path" (case insensitive).

Syntax

SelTabItemText( $hwnd, $path );

Parameters

$hwnd

Control's window handle

$path

Path to an item

Example 9.15. Select Machine item and Processors sub-item

    SelTreeViewItemPath($window, "Machine|Processors");                           
    SelTreeViewItemPath($window, "Item");

SendKeys

Sends keystrokes to the active window as if typed at the keyboard using the optional delay between keystrokes (default is 50 ms and should be OK for most uses).

Syntax

SendKeys( $keys, $delay );

Parameters

$keys

Keystrokes to be send to a window having input focus

$delay

[Optional] delay between keys strokes

Remarks

The keystrokes to send are specified in KEYS. There are several characters that have special meaning. This allows sending control codes and modifiers:

  • ~ means ENTER

  • + means SHIFT

  • ^ means CTRL

  • % means ALT

The parens allow character grouping. You may group several characters, so that a specific keyboard modifier applies to all of them.

E.g. SendKeys("ABC") is equivalent to SendKeys("+(abc)")

The curly braces are used to quote special characters (SendKeys("{+}{{}") sends a '+' and a '{'). You can also use them to specify certain named actions:

NameAction
{BACKSPACE}Backspace
{BS}Backspace
{BKSP}Backspace
{BREAK}Break
{CAPS}Caps Lock
{DELETE}Delete
{DOWN}Down arrow
{END}End
{ENTER}Enter (same as ~)
{ESCAPE}Escape
{HELP}Help key
{HOME}Home
{INSERT}Insert
{LEFT}Left arrow
{NUMLOCK}Num lock
{PGDN}Page down
{PGUP}Page up
{PRTSCR}Print screen
{RIGHT}Right arrow
{SCROLL}Scroll lock
{TAB}Tab
{UP}Up arrow
{PAUSE}Pause
{F1}Function Key 1
......
{F24}Function Key 24
{SPC}Spacebar
{SPACE}Spacebar
{SPACEBAR}Spacebar
{LWI}Left Windows Key
{RWI}Right Windows Key
{APP}Open Context Menu Key

All these named actions take an optional integer argument, like in {RIGHT 5}. For all of them, except PAUSE, the argument means a repeat count. For PAUSE it means the number of milliseconds SendKeys should pause before proceeding.

In this implementation, SendKeys always returns after sending the keystrokes. There is no way to tell if an application has processed those keys when the function returns.

SendLButtonDown

Simulates that the left mouse button is down in the current location of mouse pointer.

Syntax

SendLButtonDown();

SendLButtonUp

Simulates that the left mouse button is up in the current location of mouse pointer.

Syntax

SendLButtonUp();

SendMButtonDown

Simulates that the middle mouse button is down in the current location of mouse pointer.

Syntax

SendMButtonDown();

SendMButtonUp

Simulates that the middle mouse button is up in the current location of mouse pointer.

Syntax

SendMButtonUp();

SendMessage

The SendMessage function sends a message in to the specified window and waits until the message is processed (which is opposite to PostMessage, which posts a message and immediately returns). DO NOT think of it as simple wrapper around Win32 function! See PostMessage for details.

Syntax

$result = SendMessage( $hwnd, $msg, $wParam, $lParam );

Parameters

$hwnd

Handle of a window, to which a message is sent.

$msg

Message id

$wParam

Specifies additional message-specific information

$lParam

Specifies additional message-specific information

Return value

Value returned by window processing the message

SendMouse

This function emulates mouse input.

Syntax

SendMouse( $command );

Parameters

$command

Mouse input to be emulated

Remarks

The $command parameter is a string containing one or more of the following substrings:

NameAction
{LEFTDOWN}Left button down
{LEFTUP}Left button up
{MIDDLEDOWN}Middle button down
{MIDDLEUP}Middle button up
{RIGHTDOWN}Right button down
{RIGHTUP}Right button up
{LEFTCLICK}Left button single click
{MIDDLECLICK}Middle button single click
{RIGHTCLICK}Right button single click
{ABSx,y}Move to absolute coordinate (x,y)
{RELx,y}Move to relative coordinate (x,y)

Note: Absolute mouse coordinates range from 0 to 65535. Relative coordinates can be positive or negative. If you need pixel coordinates you can use MouseMoveAbsPix.

Also equivalent low-level functions are available:

SendMouseMoveRel

Moves a mouse cursor on the screen. Coordinates are relative to the last reported (current) position.

Syntax

SendMouseMoveRel( $rx, $ry );

Parameters

$rx

x relative normalized (0-0x10000) coordinate

$ry

y relative normalized (0-0x10000) coordinate

SendMouseMoveAbs

Moves a mouse cursor on the screen. Coordinates are relative to the upper left corner of the screen.

Syntax

SendMouseMoveAbs( $ax, $ay );

Parameters

$ax

x relative normalized (0-0x10000) coordinate

$ay

y relative normalized (0-0x10000) coordinate

SendRawKey

Wrapper around keybd_event. Allows sending low-level keys.

Syntax

SendRawKey( $virtualkey, $flags );

Parameters

$virtualkey

- any of the VK_* constants

$flags

Can be 0, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP or a combination of them

Remarks

The second argument can be 0, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP or a combination of them. Meaning of these flags is as follows:

KEYEVENTF_EXTENDEDKEY

Means it is an extended key (i.e. to distinguish between arrow keys on the numeric keypad and elsewhere).

KEYEVENTF_KEYUP

Means keyup. Unspecified means keydown.

Example 9.16. How should I title this one???

    use Win32::GuiTest qw/:FUNC :VK/;

    while(1) {
        SendRawKey(VK_DOWN, KEYEVENTF_EXTENDEDKEY); 
        SendKeys "{PAUSE 200}";
    }

SendRButtonDown

Simulates that the right mouse button is down in the current location of mouse pointer.

Syntax

SendRButtonDown();

SendRButtonUp

Simulates that the right mouse button is up in the current location of mouse pointer.

Syntax

SendRButtonUp();

SetActiveWindow

The SetActiveWindow function activates a window, but not if the application is in the background. The window will be brought into the foreground (top of Z-Order) if its application is in the foreground when the system activates the window.

Syntax

SetActiveWindow( $hwnd );

Parameters

$hwnd

Handle of a window to become active

SetFocus

The SetFocus function sets the keyboard focus to the specified window

Syntax

SetFocus( $hwnd );

Parameters

$hwnd

Handle of a window to receive focus

SetForegroundWindow

The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user.

Syntax

SetForegroundWindow( $hwnd );

Parameters

$hwnd

- Handle of a window to be moved to foreground

Return value

Returns TRUE if window was moved to foreground, FALSE otherwise.

Remarks

The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads. This is a simple wrapper around Win32 function.

SetWindowPos

The SetWindowPos function changes the size, position, and Z order of a child, pop-up, or top-level window. Child, pop-up, and top-level windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order.

Syntax

SetWindowPos( $hwnd, $hWndInsertAfter, $x, $y, $cx, $cy, $uFlags );

Parameters

$hwnd

Handle to the window

$hWndInsertAfter

Handle to the window to precede the positioned window in the Z order. Check MSDN for details

$x

Specifies the new position of the left side of the window, in client coordinates

$y

Specifies the new position of the top of the window, in client coordinates

$cx

Specifies the new width of the window, in pixels

$cy

Specifies the new height of the window, in pixels

$uFlags

Specifies the window sizing and positioning flags. This parameter can be a combination of several values. Check MSDN for details

Return value

If successful returns TRUE, FALSE otherwise.

Remarks

This is a simple wrapper around Win32 function.

ShowWindow

The ShowWindow function sets the specified window's show state. This a simple wrapper around Win32 function.

Syntax

ShowWindow( $hwnd, $cmd_show );

Parameters

$hwnd

Handle of a window to be affected

$cmd_show

Specifies how the window is to be shown. Check MSDN for details

Return value

If the window was previously visible, the return value is nonzero. If the window was previously hidden, the return value is zero.

TabCtrl_GetCurFocus

Returns the index of the item that has the focus in a tab control. This is a simple wrapper around Win32 function (actually a macro).

Syntax

$index = TabCtrl_GetCurFocus( $hwnd );

Parameters

$hwnd

Handle to the tab control

Return value

Index of an item which has a focus

TabCtrl_GetItemCount

Retrieves the number of tabs in the tab control. This is a simple wrapper around Win32 function (actually a macro).

Syntax

$icount = TabCtrl_GetItemCount( $hwnd );

Parameters

$hwnd

Handle to the tab control

Return value

Number of tabs in the tab control

TabCtrl_SetCurFocus

Sets the focus to a specified tab in a tab control. This is a simple wrapper around Win32 function (actually a macro).

Syntax

TabCtrl_SetCurFocus( $hwnd, $item );

Parameters

$hwnd

Handle to the tab control

$item

Zero-based index of the tab that gets the focus

TabCtrl_SetCurSel

Selects a tab in a tab control. This is a simple wrapper around Win32 function (actually a macro).

Syntax

$prev_idx = TabCtrl_SetCurSel( $hwnd, $item );

Parameters

$hwnd

Handle to the tab control

$item

Index of the tab to select

Return value

Returns the index of the previously selected tab if successful, or -1 otherwise.

WaitForReady

Waits until the process is ready to accept more input.

Syntax

WaitForReady( $hwnd, $timeout );

Parameters

$hwnd

Handle of any of windows owned by the process we are wating for

$timeout

Time in miliseconds after which function returns, regargdless if a process is ready or not. Default value is 30000 (30 seconds)

Remarks

Waits until the process is ready to accept more input. It is a more less a wrapper around Win32 WaitForInputIdle, which waits until process's (thread's) message queue is empty.

This function was supposed to provide an elegant solution for situations when it takes time to open a child window. Unfortunatelly it does not always work. For example it does not always work when you use Terminal Server.

WaitWindow

Minimal version of WaitWindowLike. Only requires the window title regexp. You can also specify the wait timeout in seconds.

Syntax

$hwnd = WaitWindow( $wndtitle, $wait );

Parameters

$wndtitle

Regexp for the window title

$wait

How many seconds should we wait before giving up

Return value

Handle of a found window

WaitWindowLike

Works very much like FindWindowLike. All parameters have the same meaning apart from the last one, $timeout, which is used to decide how long shall the function wait for the window to appear. Second difference is that instead of the list of window handles, WaitWindowLike returns only the first handle from the list of all windows that match the search criteria.

Syntax

$hwnd = WaitWindowLike( $parent, $titleregex, $classregex, $childid, $maxlevel, $timeout );

Parameters

$parent

Handle of a window, which children we are looking for. If undefined, handle of the desktop is assumed

$titleregex

regular expression used to match windows' caption. If not undef, only windows, which have caption matching with $titleregex will be returned. If undef, windows' caption is not considered during search

$classregex

Same as $titleregex but applies to window's class name

$childid

Control id of a child/children to be returned. If undef, $childid is not taken into consideration

$maxlevel

Maximum level in the window hierarchy tree for which child windows will be searched. Level 2 means that only direct children of $parent will be searched (which IMHO is misleading and should be changed)

$timeout

Maximum time the function should wait for the window to appear. If not given, default of 10 seconds is assumed

Return value

Handle of a found window

Remarks

The function is useful when attaching to application which has just started so it takes some time for windows to appear on the screen

Example 9.17. Finding calculator window (giving it 20 seconds to load)

    $calc_wnd = WaitWindowLike( undef, "^Calculator", undef, undef, undef, 20 );                            

WindowFromPoint

The WindowFromPoint function retrieves a handle to the window that contains the specified point. This is a simple wrapper around Win32 function.

Syntax

$hwnd = WindowFromPoint( $x, $y );

Parameters

$x

- x coordinate of the point

$y

- y coordinate of the point

Return value

Handle of a window, which has a specified point

WMGetText

Retrieves a text associated with the control (for example edited text from EditBox).

Syntax

$text = WMGetText( $hwnd );

Parameters

$hwnd

Handle to the control

Return value

Text stored in the control

Remarks

The function sends WM_GETTEXTLENGTH and then WM_GETTEXT message to a control. Check MSDN documentation on those messages.

WMSetText

Sets a text associated with the control (for example edited text in an EditBox).

Syntax

$result= WMSetText( $hwnd, $text );

Parameters

$hwnd

Handle to the control

$text

Text to be set in the control

Return value

Returns TRUE is success. Error codes depends on controls.

Remarks

The function sends WM_SETTEXT message to a control together with the text. Check MSDN documentation on this message.

WriteToVirtualBuffer

Writes to memory allocated in the address space of different process by AllocateVirtualBuffer.

Syntax

WriteToVirtualBuffer( $buf_str, $value );

Parameters

$buf_str

Reference to a hash returned by AllocateVirtualBuffer

$value

String to copied to virtual buffer

Remarks

Writes to memory allocated in the address space of different process by AllocateVirtualBuffer.

In order to understand what is this function for, have a look at advanced tutorial.

Chapter 10. Recommended reading

As for the support for the Win32::GuiTest module, there are the following places when you can look for help:

Currently, perlguitest is more active, so is you send your question there, you are more likely to get a response.

If you have some experience with perl, look at the module's documentation and the code. Look at provided examples and the test code. They are excellent in explaining how the whole thing works. If you also know C, try to get .xs file. You will see that many functions are actually simple wrappers for Win32 functions.

Understanding Win32 windowing mechanisms would be a big help. I can recommend you the following books:

  • Programming Windows 5th edition, by Charles Petzold - I can't say anything original here. Excellent book on Windows, a must read for someone who wants to get a grasp of what are Win32 all about.

  • Programming Applications for MS Windows 4th edition, by Jeffrey Richter - Another excellent book. Compared with Petzold, this book focuses more on system internals, whereas Petzold focuses on stuff related to windowing.

  • Programming Windows with MFC (2nd edition), by Jeff Prosise - Called "Petzold for MFC". Contains good explanation for toolbars and other controls.

  • Documentation for Win32 API can be found on Microsoft's MSDN.