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