views:

770

answers:

3

With Screen.DesktopHeight and Screen.DesktopWidth, I can get the size of the "virtual" desktop and I believe that works for one or multiple monitors.

I save the position (top and left) and size (height and width) of my application into the registry when it closes. When it opens, I want to ensure it is entirely visible, since it may have been moved partly outside the visible area, or the screen size may have changed for example via screen settings or removal of a monitor.

I can basically do it with this code:

if MyForm.Width > screen.DesktopWidth then 
  MyForm.Width := screen.DesktopWidth;

if MyForm.Height > screen.DesktopHeight then 
  MyForm.Height := screen.DesktopHeight;

if (MyForm.Left + MyForm.Width) > screen.DesktopWidth then 
  MyForm.Left := screen.DesktopWidth - MyForm.Width;
if MyForm.Left < 0 then MyForm.Left := 0;

if (MyForm.Top + LogoAppForm.Height) > screen.DesktopHeight then 
  MyForm.Top := screen.DesktopHeight - LogoAppForm.Height;
if MyForm.Top < 0 then MyFormTop := 0;

This works okay, except it does not take into account the taskbar that is usually (but not always) at the bottom of the desktop. So if the taskbar is in the way of my application's window, my application gets obscured.

How can I get the usable position and size settings of the screen that exclude the location of the taskbar?

+7  A: 

I'm not sure that Windows really works the way you think it does - I have multiple monitors, but they don't have the same height - so my desktop doesn't have a uniform height across all monitors.

What I do is to use Screen.MonitorCount and the Screen.Monitors array to work out which monitor contains most of the window and then find a suitable rectangle on that screen. The WorkareaRect property of TMonitor gives you the bounds of the working area on a particular monitor, which excludes any taskbars or toolbars.

garethm
Thanks for the tip. You don't give any details about how to do this, so I'll have to work it all out ... but it's the right idea.
lkessler
+7  A: 

You should use Screen.WorkArea* properties:

  Screen.WorkAreaRect
  Screen.WorkAreaHeight
  Screen.WorkAreaLeft
  Screen.WorkAreaTop
  Screen.WorkAreaWidth

or

Screen.Monitors[I].WorkareaRect
Cesar Romero
Screen.Monitors[I].WorkAreaRect is the function I need that garethm didn't mention. Thanks. Without the Monitors[I], it only gives the primary monitor. I will have to iterate through the monitors to do this correctly.
lkessler
+2  A: 

To determine the work area for the current form, use Monitor.WorkareaRect. e.g.

BoundsRect := Monitor.WorkareaRect;

to set the form size to the maximum area without maximising it.

You should also look at the TCustomForm.MakeFullyVisible method.

From D2006 help:

"MakeFullyVisible checks whether the form fits entirely on the specified monitor. If not, it repositions the form so that it fits, if possible."

Gerry
MakeFullyVisible is not quite the right function. Although it will make the form appear within the visible area, it will also change the location of the form if it is split on two monitors but entirely visible - and I don't want to move it in that latter case. But thanks for pointing this function out.
lkessler
I suspected that it may not do exactly what is wanted, I only "discovered" it recently. It doesn't seem to use the work area either.
Gerry