如何在辅助监视器上显示表单?

And*_*and 7 delphi multiple-monitors screensaver

我正在用Delphi编写一个屏幕保护程序.我想要在每个显示器上全屏显示TpresentationFrm.为此,我写了以下(不完整)程序:

program ScrTemplate;

uses
  ...

{$R *.res}

type
  TScreenSaverMode = (ssmConfig, ssmDisplay, ssmPreview, ssmPassword);

function GetScreenSaverMode: TScreenSaverMode;
begin
  // Some non-interesting code
end;

var
  i: integer;
  presentationForms: array of TpresentationFrm;

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;

  case GetScreenSaverMode of
    ssmConfig:
      Application.CreateForm(TconfigFrm, configFrm);
    ssmDisplay:
      begin
        SetLength(presentationForms, Screen.MonitorCount);
        for i := 0 to high(presentationForms) do
        begin
          Application.CreateForm(TpresentationFrm, presentationForms[i]);
          presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect;
          presentationForms[i].Visible := true;
        end;
      end
  else
    ShowMessage(GetEnumName(TypeInfo(TScreenSaverMode), integer(GetScreenSaverMode)));
  end;

  Application.Run;
end.
Run Code Online (Sandbox Code Playgroud)

ssmDisplay被执行的代码,两种形式确实是创造了(是的,我有整整两个显示器).但它们都出现在第一个监视器上(索引0,但不是主监视器).

单步执行代码时,我发现它Screen.Monitors[i].BoundsRect是正确的,但由于某种原因,表单获得了不正确的边界:

Watch Name                          Value (TRect: Left, Top, Right, Bottom, ...)
Screen.Monitors[0].BoundsRect   (-1680, 0, 0, 1050, (-1680, 0), (0, 1050))
Screen.Monitors[1].BoundsRect   (0, 0, 1920, 1080, (0, 0), (1920, 1080))

presentationForms[0].BoundsRect (-1680, 0, 0, 1050, (-1680, 0), (0, 1050))
presentationForms[1].BoundsRect (-1920, -30, 0, 1050, (-1920, -30), (0, 1050))
Run Code Online (Sandbox Code Playgroud)

第一种形式获得所需的位置,但第二种形式没有.它不是从x = 0到1920,而是占据x = -1920到0,即它出现在第一个监视器上,高于第一个窗体.怎么了?什么是完成我想要的正确程序?

Mar*_*ams 7

必须可见表单才能使用BoundRect设置边界.

颠倒这样的行:

presentationForms[i].Visible := true;
presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect;
Run Code Online (Sandbox Code Playgroud)