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;
}



Reply via email to