代码之家  ›  专栏  ›  技术社区  ›  Andreas Rejbrand

如何在辅助监视器上显示窗体?

  •  7
  • Andreas Rejbrand  · 技术社区  · 15 年前

    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

    当我一步一步地浏览代码时,我发现 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))
    

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

    3 回复  |  直到 15 年前
        1
  •  8
  •   Marcus Adams    15 年前

    presentationForms[i].Visible := true;
    presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect;
    
        2
  •  2
  •   Andreas Rejbrand    15 年前

    很明显我想过早地设定位置。

    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;
    
        3
  •  1
  •   IceCold    6 年前

    注意:如果应用程序的清单中没有包含highdpi-aware标志,则在高DPI监视器上会出现问题。在这种情况下,Windows将报告错误的(虚拟化的)绑定矩形。

    一种解决方案是手动将表单移动到您想要的屏幕上,如下所示:

    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;
    
        4
  •  0
  •   Oka Risma    4 年前

    这一步我成功了
    例如,我们想在第二个监视器上显示表单,它的索引是1

    program ARPMandiri;
    

    uses
    Vcl.Forms,
    SysUtils,
    UMain in 'UMain.pas' {frmMain},
    ........
    ..............................;

    {$R *.res}

    begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    .............
    Application.CreateForm(TfrmMain, frmMain);
    frmMain.Visible := true;
    frmMain.BoundsRect := Screen.Monitors[1].BoundsRect;
    ApplyThemes(frmMain);
    Application.Run;
    end.


    procedure TfrmMain.FormCreate(Sender: TObject);
    Var
    iTm: Integer;
    begin
    Self.Left:= Screen.Monitors[1].Left;
    Self.Top:= Screen.Monitors[1].Top;
    Self.Width:= Screen.Monitors[1].Width;
    Self.Height:= Screen.Monitors[1].Height;
    ...............

    end;