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.




Reply via email to