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 > Perl-Win32-GUI-Users@lists.sourceforge.net > 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.