How to maximize form to desktop size?

1.3k Views Asked by At

In a Delphi 10.4.2 Win32 VCL application running on Windows 10, in a dual-monitor setup, when I set my MainForm (or any other secondary form) to start maximized by setting WindowState := wsMaximized, then the form is maximized only on the Primary Monitor.

How can I maximize the Form to the whole Desktop instead, to set the Form size to include BOTH MONITORS? Is there a built-in method of the TForm class to achieve this?

3

There are 3 best solutions below

12
Andreas Rejbrand On BEST ANSWER

In general, this problem isn't as simple as you may think. I suppose you are imagining a desktop like this:

A simple desktop layout consisting of two monitors of the same size placed next to each other.

In this case, I assume you want the window to be placed like this:

A window spanning both screens.

However, what if the user has this layout:

Landscape + portrait + landscape screen setup

Do you want

Entire window visible, but some screen space unused

(entire window visible, but some screen space unused) or

No unused space, but some parts of the window not visible.

(no unused space, but some parts of the window not visible)?

If you want to use the full virtual desktop space -- the last case -- it is easy though:

BoundsRect := Screen.DesktopRect;

This will do the expected thing in a simple setup, and the "no unused space, but some parts of the window might not be visible" thing in general.

Also be aware that Windows doesn't like that windows behave like this, so the user might not get a nice experience using the app.

In general, don't do this.


Please note that even a two-monitor setup, in which both monitors are landscape, can be non-trivial:

One large monitor next to a small one.

The geometry may be non-trivial even if both monitors are the same size:

Two same-size monitors next to each other, both in landscape, but with displaced in the orthogonal direction.

4
Rob Lambden On

This is not standard behaviour for a Windows application. Also note that as the desktop can have multiple monitors which do not need to be aligned so the desktop may not be a rectangle - which means that the bounding rectangle for the desktop may contain parts which are not visible.

If you want to do this you can use the Windows function GetDesktopWindow to get the desktop window, then get its size, and then set the size of the form to that.

procedure TMyForm.GoLarge();
var
  rctDesktop:   TRect;
  hDT:          HWND;
begin
  hDT:=GetDesktopWindow();
  if(hDT<>0) then
  begin
    GetWindowRect(hDT, rctDesktop);
    Self.SetBounds(rctDesktop.Left,  rctDesktop.Top, rctDesktop.Width, rctDesktop.Height);
  end;
end;

This makes no allowance for the task bar or anything else which is using some of the desktop space.

19
Remy Lebeau On

Per MSDN:

Positioning Objects on Multiple Display Monitors

A window or menu that is on more than one monitor causes visual disruption for a viewer. To minimize this problem, the system displays menus and new and maximized windows on one monitor.

So, if you want the TForm window to stretch across the whole desktop, using WindowState=wsMaximize is not the way to go, as it will only work on the single monitor that the Form is being mostly displayed in.

To do what you ask, you will have to get the rectangle of the Virtual Screen from GetSystemMetrics() (or Vcl.Forms.TScreen), and then set the Form's Left/Top/Width/Height accordingly, eg:

if Screen.MonitorCount > 1 then
begin
  Form.WindowState := wsNormal;
  Form.Left := Screen.DesktopLeft;
  Form.Top := Screen.DesktopTop;
  Form.Width := Screen.DesktopWidth;
  Form.Height := Screen.DesktopHeight;
  // or:
  Form.SetBounds(Screen.DesktopLeft, Screen.DesktopTop, Screen.DesktopWidth, Screen.DesktopHeight);
  // or:
  Form.BoundsRect := Screen.DesktopRect;
end else
begin
  Form.WindowState := wsMaximized;
end;