Rob wrote:
> Does anyone know how I could center my
> Win32::GUI::GetOpenFileName dialog
> box in my window

Ariel Serbin wrote:
It would be very nice to
be able to have that dialog default to the thumbnail
view.


Brian wrote:
> Win32::GUI::GetOpenFileName is a hook into a Windows
> system resource, it is not a Win32::GUI object over
> which you have control.  You (the programmer) can't
> size it or position it at all.  The system will
> position it every time and, to the best of my
> knowledge, the system places it exactly where the
> user left it the last time they called it up -- with
> any program, not just your Win32::GUI application.

Close. GetOpenFileName() is a function that displays a system dialog (from comdlg32.dll). Other 'common' dialogs are font choosers, color pickers etc. - you know, all those 'standard' dialogs.

These dialogs are just windows, and if you can get the windows handle to them, you can manipulate them just like any other window (OK, this is a big generalisation, but is in, er, general, true).

All the common dialogs also (at the Win32 api level) provide hooks(callbacks) just for this purpose (for example see the GetOpenFileName() documentation at
http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/commondialogboxreference/commondialogboxfunctions/getopenfilename.asp
and look for the description of OFNHookProc). These callbacks are not supported by Win32::GUI (but could be), and would be the 'correct' way to do what you are trying to do. However, as with most perl and Win32 api things, TIMTOWTDI (There Is More Than One Way To Do It).

For example, in the code below I take advantage of the fact that when the dialog is shown, it deactivates the main window; as a result of this the main window is sent a WM_WINDOWPOSCHANGE message (as it's z-order changes), and one of the parameters passed in this message is the handle to the window that is becoming active: the handle to the dialog - we can then use that to get the size, and set the position of the dialog. There is one problem that I haven't had the time to solve, and that's how to modify the logic, so that the dialog doesn't get forced to be centered on the main window regardless - try dragging it, and see how it 'snaps' back with this code.


http://msdn.microsoft.com/msdnmag/issues/04/03/CQA/

I haven't tested this, but replacing the moving code below with code to find the handle to the lsitview (using FindWindow()?), and then using a SendMessage call, using the values from figure 5 in the link above should set the view to what you want.

Hope this helps. Please post back if you successfully solve any of the remaining problems.

Regards,
Rob.

#!perl -w
use strict;
use warnings;

use Win32::GUI;

sub WM_WINDOWPOSCHANGING() {70}
sub SWP_NOACTIVATE()       {16}

my $mw = Win32::GUI::Window->new(
        -title => "GetOpenFileName Test",
        -pos   => [100,100],
        -size  => [400,300],
);
$mw->Hook(WM_WINDOWPOSCHANGING, \&PosChanging);

$mw->AddButton(
        -text    => "Browse ...",
        -pos     => [10,10],
        -onClick => \&Browse,
);

$mw->Show();
Win32::GUI::Dialog();
exit(0);

sub Browse
{
        Win32::GUI::GetOpenFileName(
                -owner => $mw,
        );

        return;
}

sub PosChanging
{
        my ($object, $wParam, $lParam, $type, $msgcode) = @_;
        return unless $type == 0;
        return unless $msgcode == WM_WINDOWPOSCHANGING;

        # unpack WINDOWPOS structure
# http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowstructures/windowpos.asp
        my($hwnd, $hwndInsertAfter, $x, $y, $cx, $cy, $flags) =
                unpack("LLiiiiI", unpack("P28", pack("L",$lParam)));
        
        # check that it's us (this is probably not necessary)
        return unless $hwnd == $object->{-handle};

        # check that the handle in $hwndInsertAfter is for the Open File dialog:
        # here I test the window caption, but you might need something more 
robust:
        return unless Win32::GUI::Text($hwndInsertAfter) eq "Open";

        # only interested in doing something if we're being de-activated
        # for the first time: this test needs enhancing, so that dragging
        # the dialog works, and we don't move it back to the center when we
        # release the mouse
        return unless $flags & SWP_NOACTIVATE;

        # modify the Dialog (center it on the main window):
my $sx = $mw->Left() + ($mw->Width() - Win32::GUI::Width($hwndInsertAfter))/2; my $sy = $mw->Top() + ($mw->Height() - Win32::GUI::Height($hwndInsertAfter))/2;
        Win32::GUI::Move($hwndInsertAfter, $sx, $sy);

        # set the view:
        # from http://msdn.microsoft.com/msdnmag/issues/04/03/CQA/
        # 0x7029        Icons
        # 0x702B        List
        # 0x702C        Details
        # 0x702D        Thumbnails
        # 0x702E        Tiles

        # Find the listview handle:
        # my $lv_hwnd = ????
        # Win32::GUI::SendMessage($lv_hwnd, WM_COMMAND, 0x702C, 0);

        return;
}

Reply via email to