How can I display the form on the secondary monitor?

I am writing a screensaver in Delphi. I want to show TpresentationFrm on each monitor, in full screen mode. To this end, I wrote the following (incomplete) program:

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. 

When the ssmDisplay code is ssmDisplay , two forms are really created (yes, I have exactly two monitors). But they both appear on the first monitor (index 0, but not the main one).

When navigating through the code, I see that Screen.Monitors[i].BoundsRect are correct, but for some reason the forms get the wrong borders:

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

The first form gets the desired position, and the second does not. Instead of moving from x = 0 to 1920, it takes from x = -1920 to 0, that is, it appears on the first monitor above the first form. What's wrong? What is the proper procedure for doing what I want?

+7
delphi multiple-monitors screensaver
source share
3 answers

The shape must be visible in order to set borders using a BoundRect.

Turn the lines like this:

 presentationForms[i].Visible := true; presentationForms[i].BoundsRect := Screen.Monitors[i].BoundsRect; 
+7
source share

Apparently, I'm trying to establish a position prematurely.

Replace the for loop block with

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

and then write

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

You will have problems with high DPI monitors if your application does not include a high-definition flag in its manifest. In this case, Windows will report an incorrect (virtualized) bound rectangle.

One solution would be to manually move the form to the screen you need:

 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; 
0
source share

All Articles