2010-06-25 28 views
7

Estoy escribiendo un protector de pantalla en Delphi. Quiero mostrar un TpresentationFrm en cada monitor, pantalla completa. Con este fin, he escrito el siguiente programa (incompleta):¿Cómo puedo mostrar un formulario en un monitor secundario?

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. 

Cuando se ejecuta el código ssmDisplay, dos formas se crean de hecho (sí, tengo exactamente dos monitores). Pero ambos aparecen en el primer monitor (índice 0, pero no el primario).

Al recorrer el código, veo que la Screen.Monitors[i].BoundsRect son correctas, pero por alguna razón las formas obtener cotas incorrectas:

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

La primera forma de conseguir la posición deseada, pero el segundo no. En lugar de pasar de x = 0 a 1920, ocupa x = -1920 a 0, es decir, aparece en el primer monitor, encima de la primera forma. ¿Qué está mal? ¿Cuál es el procedimiento adecuado para lograr lo que quiero?

+0

tendrá problemas en monitores de alta DPI si su aplicación no incluye la bandera highdpi cuenta en su manifiesto. En este caso, Windows informará un rectángulo encuadernado incorrecto (virtualizado). – Ampere

Respuesta

7

La forma tiene que ser visible a fin de establecer los límites utilizando BoundRect.

Invertir las líneas de este tipo:

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

Sí, solo tengo que cambiar las dos líneas en el bucle 'for': establezca primero la visibilidad y luego cambie los límites. –

2

Aparentemente trato de establecer la posición prematuramente.

Reemplazar el bloque for bucle con

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

y luego escribir

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

tendrá problemas en monitores de alta DPI si su aplicación no incluye la bandera highdpi cuenta en su manifiesto. En este caso, Windows informará un rectángulo encuadernado incorrecto (virtualizado).

Una solución sería mover manualmente la forma de la pantalla que desea de esta manera:

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; 
Cuestiones relacionadas