Ted W
Ted W

Reputation: 248

Delphi: How to restore a form's original location when monitor configuration changes?

I have a multi-form application in which a child form is positioned on the second monitor on startup, at which time its BoundsRect is saved.

When the computer's display configuration changes, Windows moves the form to the first (primary) monitor. I can catch this change with WM_DISPLAYCHANGE:

procedure WMDisplayChange(var msg: TWMDisplayChange); message WM_DISPLAYCHANGE;

What I'm interested in doing is moving the child form back to the second monitor when it reappears in the configuration (i.e. Screen.MonitorCount goes from 1 to 2), e.g.:

childForm.BoundsRect := childForm.m_WorkingBounds;
// (or)
childForm.BoundsRect := Screen.Monitors[Screen.MonitorCount-1].BoundsRect;

However this assignment is have no affect -- the child form stays on monitor 0.

I've tried other approaches, such as SetWindowPos(), with no success ...

Upvotes: 2

Views: 817

Answers (2)

I tested this with old version Delphi5 and it worked easy just to:

Screen.Free;
Screen := TScreen.Create(Nil);

The screen handling has changed in later versions of Delphi, however a similar approach may work.

Upvotes: 0

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28516

Root of your problem is in the fact that Delphi VCL does not refresh its internal list of monitors when they actually change. You have to force that refresh yourself.

Monitors are refreshed with TScreen.GetMonitors method that is unfortunately private method so you cannot call it directly.

However, TApplication.WndProc(var Message: TMessage) processes WM_WTSSESSION_CHANGE and upon receiving that message it calls Screen.GetMonitors - this is most benign way to achieve your goal.

When you receive notifications that monitors are changed just send it to Application:

SendMessage(Application.Handle, WM_WTSSESSION_CHANGE, 0, 0);

Upvotes: 5

Related Questions