Ariel Serbin wrote:
1. Win32::GUI::FindWindow only finds top level windows
(which is what it says in the docs.)
The docs are correct! I was thinking of FindWindowEx, which is not in
Win32::GUI.
I had to install
Win32::GuiTest to get the handle of the listview
control in the Open dialog.
There's some code below to show a way of walking the window
hierarchy using GetWindow() - although EnumChildWindows() is safer
according to msdn.
2. The event in that example is fired when the file
open dialog opens, however GuiTest's FindWindowLike
function doesn't seem to be finding the control at
that point. When I click on the dialog, the event
fires again and it finds the control.
It appears that the dialog has not finished initialising the first time
the dialog sends the WM_WINDOWPOSCHANGING message. There is another
message sent by the dialog: WM_ENTERIDLE, which is sent every time the
dialog's message loop finishes processing all the messages in its queue.
By Hook()ing that message, we get to do our processing after
everything is initialised fully.
I've also moved the Hook() call to just before we do the
GetOpenFileName() call, and I UnHook() the message as soon as we see one
- this ensures that we only position the dialog and set the view mode
once each time we display it. (UnHook() causes a warning on my perl
5.8.7, Win32::GUI 1.02 - I raised a tracker for this some time ago). [If
the warnings irritate you, then a similar effect could be achieved with
a global variable set to 0 in the Browse function, and set to 1 in the
Idle function, with a test at the start of the Idle function.]
Regards,
Rob.
#!perl -w
use strict;
use warnings;
use Win32::GUI;
sub WM_WINDOWPOSCHANGING() {70}
sub WM_ENTERIDLE() {289}
sub SWP_NOACTIVATE() {16}
sub MSGF_DIALOGBOX() {0}
my $mw = Win32::GUI::Window->new(
-title => "GetOpenFileName Test",
-pos => [100,100],
-size => [400,300],
);
$mw->AddButton(
-text => "Browse ...",
-pos => [10,10],
-onClick => \&Browse,
);
$mw->Show();
Win32::GUI::Dialog();
exit(0);
sub Browse
{
$mw->Hook(WM_ENTERIDLE, \&Idle);
Win32::GUI::GetOpenFileName(
-owner => $mw,
);
return;
}
sub Idle
{
print "Idle hook\n";
$mw->UnHook(WM_ENTERIDLE); # ensure this hook doesn't get called again
my ($object, $wParam, $lParam, $type, $msgcode) = @_;
return unless $type == 0;
return unless $msgcode == WM_ENTERIDLE;
# check the message came from a dialog box
return unless $wParam == MSGF_DIALOGBOX;
# check that the dialog window handle in $lParam is for the Open File
dialog:
# here I test the window caption, but you might need something more
robust:
return unless Win32::GUI::Text($lParam) eq "Open";
# modify the Dialog (center it on the main window):
my $sx = $mw->Left() + ($mw->Width() - Win32::GUI::Width($lParam))/2;
my $sy = $mw->Top() + ($mw->Height() - Win32::GUI::Height($lParam))/2;
Win32::GUI::Move($lParam, $sx, $sy);
# Walk the child windows of the open dialog to find the
SHELLDLL_DefView window:
my $phwnd = $lParam;
my $mode = GW_CHILD; # Initially find the first child of the dialog
window
while(my $chwnd = Win32::GUI::GetWindow($phwnd, $mode)) {
if (Win32::GUI::GetClassName($chwnd) eq "SHELLDLL_DefView") {
# set the view:
# from
http://msdn.microsoft.com/msdnmag/issues/04/03/CQA/
# 0x7029 Icons
# 0x702B List
# 0x702C Details
# 0x702D Thumbnails
# 0x702E Tiles
Win32::GUI::SendMessage($chwnd, WM_COMMAND, 0x702C, 0);
last; # we found it
}
$mode = GW_HWNDNEXT; # and walk the rest of the dialog's
children
$phwnd = $chwnd;
}
return;
}