2010-06-25 11 views
7

저는 델파이에서 스크린 세이버를 씁니다. 내가 원하는 것은 TpresentationFrm을 각 모니터에 전체 화면으로 표시하는 것입니다. ssmDisplay 코드가 실행되면보조 모니터에 양식을 표시하려면 어떻게합니까?

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. 

, 두 가지 형태가 실제로 생성됩니다 (예, 정확히 두 개의 모니터가) :이를 위해, 나는 다음 (불완전) 프로그램을 작성했습니다. 하지만 둘 다 첫 번째 모니터에 나타납니다 (인덱스 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)) 

첫 번째 형태는 원하는 위치를 얻을 수 있지만, 두 번째는하지 않습니다. x = 0에서 1920으로 이동하는 대신 x = -1920에서 0을 차지합니다. 즉, 첫 번째 모니터 위에 첫 번째 양식 위에 나타납니다. 뭐가 잘못 되었 니? 내가 원하는 것을 성취하기위한 적절한 절차는 무엇입니까?

+0

당신은 높은 DPI 모니터에 문제가있는 것입니다. 이 경우 Windows는 잘못된 (가상화 된) 바운드 사각형을보고합니다. – Ampere

답변

7

물품.

이 같은 라인을 역

: 응용 프로그램 매니페스트에서 highdpi 인식 플래그를 포함하지 않는 경우

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

예, 'for' 루프에서 두 줄을 바꾸기 만하면됩니다 : 가시성을 먼저 설정 한 다음 경계를 변경하십시오! –

2

분명히 나는 ​​위치를 조기에 설정하려고합니다.

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

으로 for 루프 블록을 교체 한 후 폼 BoundRect를 사용하여 경계를 설정하기 위해 표시하는

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

당신은 높은 DPI 모니터에 문제가있는 것입니다. 이 경우 Windows는 잘못된 (가상화 된) 바운드 사각형을보고합니다.

한 가지 해결책은 수동으로 다음과 같이 원하는 화면으로 양식을 이동하는 것입니다 : 응용 프로그램 매니페스트에서 highdpi 인식 플래그를 포함하지 않는 경우

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; 
관련 문제