8 Stimmen

Wie kann ich ein Formular auf einem zweiten Monitor anzeigen?

Ich schreibe gerade einen Bildschirmschoner in Delphi. Ich möchte einen TpresentationFrm auf jedem Monitor im Vollbildmodus anzeigen. Zu diesem Zweck habe ich das folgende (unvollständige) Programm geschrieben:

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.

Wenn die ssmDisplay Code ausgeführt wird, werden tatsächlich zwei Formulare erstellt (ja, ich habe genau zwei Monitore). Aber sie erscheinen beide auf dem ersten Monitor (Index 0, aber nicht der primäre).

Wenn ich durch den Code gehe, sehe ich, dass die Screen.Monitors[i].BoundsRect sind korrekt, aber aus irgendeinem Grund erhalten die Formulare falsche Grenzen:

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))

Bei der ersten Form wird die gewünschte Position erreicht, bei der zweiten jedoch nicht. Anstatt von x=0 bis 1920 zu gehen, nimmt es x=-1920 bis 0 ein, d.h. es erscheint auf dem ersten Bildschirm, über dem ersten Formular. Was ist hier falsch? Wie gehe ich richtig vor, um das zu erreichen, was ich will?

9voto

Marcus Adams Punkte 51234

Das Formular muss sichtbar sein, damit die Begrenzungen mit BoundRect festgelegt werden können.

Drehen Sie die Zeilen so um:

presentationForms[i].Visible := true;
presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect;

2voto

Andreas Rejbrand Punkte 100651

Offenbar versuche ich, die Position zu früh festzulegen.

Ersetzen Sie die for Schleifenblock mit

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

und schreiben dann

procedure TpresentationFrm.FormShow(Sender: TObject);
begin
  BoundsRect := Screen.Monitors[Tag].BoundsRect;
end;

1voto

Server Overflow Punkte 19774

Hinweis: Auf Monitoren mit hohem DPI-Wert treten Probleme auf, WENN Ihre Anwendung das Flag highdpi aware nicht in ihr Manifest aufnimmt. In diesem Fall wird Windows ein falsches (virtualisiertes) gebundenes Rechteck melden.

Eine Lösung wäre, das Formular manuell auf den gewünschten Bildschirm zu verschieben, etwa so:

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;

0voto

Oka Risma Punkte 1

Dieser Schritt ist mir gelungen
Wir wollen zum Beispiel das Formular auf dem zweiten Monitor anzeigen, sein Index ist 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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X