Delphi:如何在监视器配置发生变化时恢复表单的原始位置?

时间:2016-10-26 15:51:51

标签: forms delphi

我有一个多表单应用程序,其中子表单在启动时位于第二个监视器上,此时它的BoundsRect被保存。

当计算机的显示配置发生变化时,Windows会将表单移动到第一个(主)监视器。我可以用WM_DISPLAYCHANGE:

来捕捉这个变化
procedure WMDisplayChange(var msg: TWMDisplayChange); message WM_DISPLAYCHANGE;

我感兴趣的是将子窗体返回移动到第二个监视器,当它再次出现在配置中时(即Screen.MonitorCount从1变为2),例如:< / p>

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

然而,此作业没有任何影响 - 子表单保留在监视器0上。

我尝试过其他方法,例如SetWindowPos(),但没有成功......

2 个答案:

答案 0 :(得分:5)

问题的根源在于Delphi VCL在实际更改时不会刷新其内部监视器列表。你必须自己强制刷新。

使用TScreen.GetMonitors方法刷新监视器,不幸的是私有方法,因此您无法直接调用它。

但是,TApplication.WndProc(var Message: TMessage)处理WM_WTSSESSION_CHANGE并在收到该消息后调用Screen.GetMonitors - 这是实现目标的最佳方式。

当您收到更改监视器的通知时,只需将其发送到应用程序:

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

答案 1 :(得分:0)

我使用旧版本的Delphi5进行了测试,它只是简单地用于:

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

在Delphi的更高版本中,屏幕处理已经改变,但是类似的方法可能会有效。