OK, here's sample Perl/Win32::GUI/Win32::API code for positioning windows on the
desktop while avoiding any/all Windows "appbars" and the Windows "taskbar"
(which
was the first appbar, and still seems to be a bit special among appbars). If
you
don't like my "negative number means right or bottom" stuff, just take it out :)
Thanks to Harald for the kernel knowledge that got me started, and the attaboy
along
the way.
This code attempts to keep the full window visible, so if/when you want to allow
part of the windows to float off-screen, or under the taskbars, well, don't use
this
code, or modify it appropriately.
#####################################
sub make_get_work_area
{ my $spi;
$spi = new Win32::API ( 'user32', 'SystemParametersInfo',
[ 'I', 'I', 'P', 'I' ], 'I' );
return $spi;
}
#####################################
sub call_get_work_area
{ my ( $spi ) = @_;
my ( $rect ) = pack ( "LLLL", 0, 0, 0, 0 );
my ( $ret ) = $spi -> Call ( 48, 0, $rect, 0 );
unless ( $ret )
{
}
return unpack ( "LLLL", $rect );
}
#####################################
{ my $spi;
sub working_area
{ my ( $winx, $winy, $winw, $winh ) = @_; # proposed position, actual size
# If no parameters are passed in, this function returns the working area
# of the desktop, ( left, top, right, bottom ). If parameters are passed
# in, it returns the "best" ( left, top, width, height ) position for the
# specified window, starting with the proposed position, adjusting it so
# that as much as possible of the window will be visible, and further
# adjusting it so that the top left corner of the window will be visible.
# Negative positions are interpreted as "bottom" or "right", as appropriate.
# first, obtain the non-toolbar area of the desktop.
$spi = & make_get_work_area () unless $spi;
print "$spi\n";
my ( @limits );
@limits = & call_get_work_area ( $spi );
print "limits: @limits\n";
# limits returned unless all parameters supplied
return @limits unless defined $winx && defined $winy
&& defined $winw && defined $winh;
print "before adjustments: x=$winx y=$winy w=$winw h=$winh\n";
$winy = $limits [ 3 ] - $winh
if $winy < 0 || $winy + $winh > $limits [ 3 ];
$winx = $limits [ 2 ] - $winw
if $winx < 0 || $winx + $winw > $limits [ 2 ];
$winy = $limits [ 1 ] if $winy < $limits [ 1 ];
$winx = $limits [ 0 ] if $winx < $limits [ 0 ];
print "x=$winx y=$winy w=$winw h=$winh\n";
return ( $winx, $winy, $winw, $winh );
}
}
#####################################
Glenn Linderman wrote:
> "Piske, Harald" wrote:
>
> > I'm impressed - here's somebody who knows how to translate general ideas
> > into formal terminology.
>
> Thanks for the attaboy. It was just what I needed to inspire further
> research...
>
> > I don't have a solution at hand but with what you
> > say, you should be able to figure it out. I'm not aware of any ready-made
> > windoze function to give you the "effective desktop client area after
> > accounting for taskbars", but that does not mean there is none. I'm not
> > really at home in the win ref manuals.
>
> I am. Now. Post research :) Research is below for the interested. Next
> research project is to figure out how to use Win32::API well enough to benefit
> from the research...
>
> > Just one more note: my wife has a toolbar on her computer that is nothing
> > but a small collection of buttons. Looks like it was invented before Win98
> > came along with it's quick-launch thingy. That is only around 10% of the
> > screen width and just one row of icons high.
>
> I've seen some of those. Not too concerned about them, either.
>
> Here's the relevant pieces of the results of the research through MSDN:
>
> BOOL SystemParametersInfo(
> UINT uiAction, // system parameter to query or set
> UINT uiParam, // depends on action to be taken
> PVOID pvParam, // depends on action to be taken
> UINT fWinIni // user profile update flag
> );
>
> when uiAction == SPI_GETWORKAREA
>
> Retrieves the size of the work area on the primary display monitor. The work
> area is the portion of the screen not obscured by the system taskbar or by
> application desktop toolbars. The pvParam parameter must point to a RECT
> structure that receives the coordinates of the work area, expressed in virtual
> screen coordinates.
>
> To get the work area of a monitor other than the primary display monitor, call
> the GetMonitorInfo function.
>
> RECT
>
> The RECT structure defines the coordinates of the upper-left and lower-right
> corners of a rectangle.
>
> typedef struct _RECT {
> LONG left;
> LONG top;
> LONG right;
> LONG bottom;
> } RECT;
>
> Members
> left Specifies the x-coordinate of the upper-left corner of the rectangle.
> top Specifies the y-coordinate of the upper-left corner of the rectangle.
> right Specifies the x-coordinate of the lower-right corner of the rectangle.
> bottom Specifies the y-coordinate of the lower-right corner of the rectangle.
>
> Remarks
>
> When RECT is passed to the FillRect function, the rectangle is filled up to,
> but
> not including, the right column and bottom row of pixels. This structure is
> identical to the RECTL structure.
>
> So it looks like the C/C++ code for this would go approximately like:
>
> RECT workarea;
> BOOL ret;
>
> ret = SystemParametersInfo ( SPI_GETWORKAREA, 0, & workarea, 0 );
> if ( ! ret )
> { ... GetLastError ...
> }
> // workarea can be determined from workarea.left, workarea.top, etc.
>
> --
> Glenn
> =====
> Due to the current economic situation, the light at the
> end of the tunnel will be turned off until further notice.
>
> _______________________________________________
> Perl-Win32-GUI-Users mailing list
> [email protected]
> http://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
--
Glenn
=====
Due to the current economic situation, the light at the
end of the tunnel will be turned off until further notice.