2010-06-25 23 views
7

Ich schreibe einen Bildschirmschoner in Delphi. Ich möchte ein TpresentationFrm auf jedem Monitor im Vollbildmodus anzeigen. Zu diesem Zweck habe ich das folgende (unvollständige) Programm geschrieben:Wie kann ich ein Formular auf einem sekundären Monitor anzeigen?

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 der ssmDisplay Code ausgeführt wird, werden zwei Formen in der Tat geschaffen (ja, ich habe genau zwei Monitore). Aber beide erscheinen auf dem ersten Monitor (Index 0, aber nicht der erste).

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

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

Die erste Form die gewünschte Position bringen, aber die zweite nicht. Statt von x = 0 bis 1920 geht es von x = -1920 nach 0, d. H. Es erscheint auf dem ersten Monitor über der ersten Form. Was ist falsch? Was ist das richtige Verfahren, um das zu erreichen, was ich will?

+0

Sie Probleme auf hohen DPI-Monitore haben, wenn Ihre Anwendung nicht die highdpi in seinem Manifest bewusst Flagge enthält. In diesem Fall meldet Windows ein falsches (virtualisiertes) gebundenes Rechteck. – Ampere

Antwort

7

Die Form, um den Rahmen unter Verwendung von BoundRect einzustellen sichtbar sein muss schreiben.

die Zeilen wie diese Reverse:

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

Ja, ich muss nur die beiden Zeilen in der 'for'-Schleife vertauschen: setze zuerst die Sichtbarkeit und dann die Grenzen! –

2

Anscheinend versuche ich die Position vorzeitig einzustellen.

Ersetzen der for Block Schleife mit

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

und dann

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

Sie Probleme auf hohen DPI-Monitore haben, wenn Ihre Anwendung die highdpi bewusst Flagge in seinem Manifest nicht enthalten. In diesem Fall meldet Windows ein falsches (virtualisiertes) gebundenes Rechteck.

Eine Lösung wäre, das Formular manuell auf dem Bildschirm bewegen Sie so wollen:

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; 
Verwandte Themen