Piotr Kaluski wrote:
Hi,
I am one of developers of Win32::GuiTest library. It is a module for GUI
test automation. I am actually pretty impressed with all the great work
you have done. Using your module should free us from writing some
functions ourselves.
I have one question. My impression is, that your library is object
oriented and it assumes, that a script using it has actually created all
windows it manipulates. Is it possible to attach to a window/control
created by some other application? Say I have a handle of a main window of
Windows calculator. How do I turn it into Win::GUI object?
Firstly I'd like to iterate Jeremy's reply that most of the method calls
in Win32::GUI (and especially the ones that have underlying w32api
calls that operate on handles) are overloaded, so that they can be
called statically with an extra first parameter that is a window handle,
so Win32::GUI is not limited to working with objects that it created
itself. At the bottom is a (rather messy and hastily thrown together)
script that enumerates the windows you have on your desktop, and allows
you to minimise/restore then, showing how this can be done. This usage
is also touched on in Part 1 of the tutorial
(http://perl-win32-gui.sourceforge.net/docs/Win32/GUI/Tutorial/Part1.html#centring_the_window_and_the_text)
It is an interesting time for this conversation to come up, as we have
been touching the subject of testing on the hackers list a few times in
recent months, and if you were to look in the TODO file in CVS you would
see that I added a comment yesterday that I was leaning towards a
Win32::GUI::Test package. I have not discussed my reasoning yet (and my
position is still forming) but I'll try to outline my thinking. Please
bear in mind that I haven't given Win32::GuiTest more than a cursory
glance yet, and that nothing is set in stone.
(1) As a Win32::GUI developer I am primarily looking at a package that
will simplify writing tests for the Win32::GUI distribution. That said,
our users would almost certainly benefit from a well written test
package for testing their own applications.
(2) Whatever package we end up with must be readily usable within the
standard perl test framework: this means being able to write tests that
run under the Test::Harness framework, and can be invoked using 'make
test' and 'prove'.
(3) I'd prefer not to have to make an external package a pre-requsite
for building and testing Win32::GUI - but will continue to consider it
as I have no desire to re-generate good work that has already been done
by someone else. I would be very interested in seeing a list of the
win32api functions that Win32::GuiTest uses, so that we could see how
much we would need to add to Win32::GUI to get the same functionality.
As Ariel points out in his reply there are certainly calls missing from
Win32::GUI - things that I am sure we would need that spring to mind are
EnumWindows, EnumChildWindows and FindWindowEx - but these and others
really should be in Win32::GUI, so I'd have no problems adding them.
So, from a Win32:GUI point of view I would think that building
Win32::Gui::Test on top of the existing Win32::GUI framework makes a lot
of sense. From a Win32::GuiTest point of view I think there needs to be
some thought as to whether having it installable as a separate module,
without Win32::GUI makes sense - as has already been mentioned,
Win32::GUI is not a small download, and may be rather heavy-weight for
someone looking for a test framework to test Win32 paps built in other
environments.
Regards,
Rob.
#!perl -w
use strict;
use warnings;
use Win32::GUI;
my $winInfo;
my $selHwnd = 0;
my $mw = Win32::GUI::DialogBox->new(
-title => $0,
-pos => [100,100],
-size => [300,100],
-helpbutton => 0,
);
my $c = $mw->AddCombobox(
-pos => [10,10],
-size => [$mw->ScaleWidth()-20,100],
-sort => 1,
-vscroll => 1,
-onChange => \&Select,
-dropdownlist => 1,
);
$mw->AddButton(
-text => "Refresh",
-pos => [10, $mw->ScaleHeight()-30],
-size => [60,20],
-onClick => sub {populateCombo($c); 0;},
);
my $b = $mw->AddButton(
-text => "Minimize",
-pos => [$mw->ScaleWidth()-70, $mw->ScaleHeight()-30],
-size => [60,20],
-onClick => \&Action,
);
populateCombo($c);
$mw->Show();
Win32::GUI::Dialog();
exit(0);
sub populateCombo
{
my $c = shift;
$selHwnd = 0;
$b->Enable(0);
$winInfo = WindowList();
$c->Clear();
for my $w (keys %$winInfo) {
$c->Add($w);
}
}
sub WindowList
{
my %windows;
# walk all the top level windows (immediate children of desktop):
my $hwnd = Win32::GUI::GetDesktopWindow();
my $mode = GW_CHILD;
while( $hwnd = Win32::GUI::GetWindow($hwnd, $mode) ) {
$mode = GW_HWNDNEXT;
next unless Win32::GUI::IsWindow($hwnd);
next unless Win32::GUI::IsVisible($hwnd);
my $text = Win32::GUI::Text($hwnd);
$windows{$text} = $hwnd if length($text) > 0;
}
return \%windows;
}
sub Action
{
my $b = shift;
return unless Win32::GUI::IsWindow($selHwnd);
if($b->Text() eq "Minimize") {
Win32::GUI::Minimize($selHwnd);
}
else {
Win32::GUI::Restore($selHwnd);
}
$b->Text( Win32::GUI::IsIconic($selHwnd) ? "Restore" : "Minimize" );
return;
}
sub Select
{
my $c = shift;
$selHwnd = $winInfo->{$c->GetLBText($c->GetCurSel())};
return unless Win32::GUI::IsWindow($selHwnd);
$b->Enable(1);
$b->Text( Win32::GUI::IsIconic($selHwnd) ? "Restore" : "Minimize" );
return;
}