8

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.

ssmDisplayコードが実行されると、実際に 2 つのフォームが作成されます (はい、ちょうど 2 つのモニターがあります) 。ただし、両方とも最初のモニターに表示されます (インデックス 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))

最初のフォームは目的の位置を取得しますが、2 番目のフォームは取得しません。x=0 から 1920 に移動する代わりに、x=-1920 から 0 を占有します。つまり、最初のモニターの最初のフォームの上に表示されます。なにが問題ですか?私が望むものを達成するための適切な手順は何ですか?

4

4 に答える 4

9

BoundRect を使用して境界を設定するには、フォームが表示されている必要があります。

次のように行を逆にします。

presentationForms[i].Visible := true;
presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect;
于 2010-06-25T14:35:24.370 に答える
2

どうやら時期尚早に位置を設定しようとしています。

ループforブロックを

Application.CreateForm(TpresentationFrm, presentationForms[i]);
presentationForms[i].Tag := i;
presentationForms[i].Visible := true;

そして書く

procedure TpresentationFrm.FormShow(Sender: TObject);
begin
  BoundsRect := Screen.Monitors[Tag].BoundsRect;
end;
于 2010-06-25T14:32:05.780 に答える
1

注: アプリケーションのマニフェストに highdpi 対応フラグが含まれていない場合、高 DPI モニターで問題が発生します。この場合、Windows は間違った (仮想化された) 境界四角形を報告します。

1 つの解決策は、次のようにフォームを手動で画面に移動することです。

procedure MoveFormToScreen(Form: TForm; ScreenNo: Integer);
begin
 Assert(Form.Position= poDesigned);
 Assert(Form.Visible= TRUE);

 Form.WindowState:= wsNormal;
 Form.Top := Screen.Monitors[ScreenNo].Top;
 Form.Left:= Screen.Monitors[ScreenNo].Left;
 Form.WindowState:= wsMaximized;
end;
于 2017-12-14T13:21:59.957 に答える