Delphi 7:多个监视器上的中心表格位置

Kaw*_*hii 1 delphi delphi-7

我有一个TForm,我将"位置"设置为poMainFormCenter.

当我打开该表单时,它会在主表单的中心正确显示.

但是,在多个屏幕(2个监视器)上,当我将应用程序放在辅助监视器中时,该窗体不会显示在主窗体的中心.

它仍显示在主监视器中,位于屏幕边缘.

我的应用程序没什么特别的,我只设置了Position属性.

有人知道怎么修这个东西吗?

我使用的是Delphi 7和Windows XP SP3.

Lor*_*tel 5

除了看鼠标外,Jlouro有正确的想法.Screen.Monitors []包含每个屏幕的信息.

我有一个标准程序,通过监视器列表,并找出左上角的位置,以决定将它放在哪个监视器上.虽然我的代码没有居中(我只是在确保窗口完全在它出现的任何监视器之后),但这个想法仍然是一样的.请注意,您必须考虑窗口不显示在任何监视器上的情况 - 我通过将其扔到第一个监视器来处理它.(这将在保存的位置在不再存在的监视器上时发生 - 在另一台计算机上移除或运行.)

自从我搞砸了很长一段时间以来,它没有给我带来任何麻烦,所以我没有在比XP/Delphi 7更新的任何东西上测试它.

请注意,这仅仅是为了确保表单可见并且完全在一个监视器上,不会尝试将其居中.

Function        PointInBox(x, y, x1, y1, x2, y2 : Integer) : Boolean;

Begin
    Result := (X >= X1) And (X <= X2) And (Y >= Y1) And (Y <= Y2);
End;

Function        Overlapping(x11, y11, x12, y12, x21, y21, x22, y22 : Integer) : Boolean;

Var
    tx1, ty1, tx2, ty2      : Integer;

Begin
    Tx1 := Max(x11, x21);
    Tx2 := Min(x12, x22);
    Ty1 := Max(y11, y21);
    Ty2 := Min(y12, y22);
    Result := (Tx1 < Tx2) And (Ty1 < Ty2);
End;

Function        GetWhere(Form : TForm) : Integer;

Var
    Loop        : Integer;
    Where       : Integer;

Begin
    Where           := -1;
    For Loop := 1 to Screen.MonitorCount do
        With Screen.Monitors[Loop - 1] do
            If PointInBox(Form.Left, Form.Top, Left, Top, Left + Width - 1, Top + Height - 1) then
                Where := Loop - 1;
    If Where = -1 then // Top left corner is wild, check for anything
        For Loop := 1 to Screen.MonitorCount do
            With Screen.Monitors[Loop - 1] do
                If Overlapping(Form.Left, Form.Top, Form.Left + Form.Width - 1, Form.Top + Form.Height - 1, Left, Top, Left + Width - 1, Top + Height - 1) then
                    Where := Loop - 1;
    Result := Where;
End;

Procedure   GetLimits(Where : Integer; var X, Y, WWidth, WHeight : Integer);

Var
    R               : TRect;

Begin
    If Where < 0 then
        Begin
            SystemParametersInfo(Spi_GetWorkArea, 0, @R, 0);
            X           := R.Left;
            Y           := R.Top;
            WWidth  := R.Right - R.Left + 1;
            WHeight := R.Bottom - R.Top + 1;
        End
    Else With Screen.Monitors[Where] do
        Begin
            X           := Left;
            Y           := Top;
            WWidth  := Width;
            WHeight := Height;
        End;
End;

Procedure   EnsureValidDisplay(Form : TForm);

Var
    Left            : Integer;
    Top         : Integer;
    Width           : Integer;
    Height      : Integer;
    Where           : WindowPlacement;

Begin
    GetLimits(GetWhere(Form), Left, Top, Width, Height);
    Where.Length    := SizeOf(Where);
    Where.Flags     := 0;
    GetWindowPlacement(Form.Handle, @Where);
    If Form.Left < Left then
        Where.rcNormalPosition.Left := Left
    Else If Form.Left + Form.Width > Left + Width then
        Where.rcNormalPosition.Left := Left + Width - Form.Width;
    If Form.Top < Top then
        Where.rcNormalPosition.Top      := Top
    Else If Form.Top + Form.Height > Top + Height then
        Where.rcNormalPosition.Top      := Top + Height - Form.Height;
    If Form.Width > Width then
        Where.rcNormalPosition.Right    := Where.rcNormalPosition.Left + Width
    Else
        Where.rcNormalPosition.Right    := Where.rcNormalPosition.Left + Form.Width;
    If Form.Height > Height then
        Where.rcNormalPosition.Bottom   := Where.rcNormalPosition.Top + Height
    Else
        Where.rcNormalPosition.Bottom   := Where.rcNormalPosition.Top + Form.Height;
    SetWindowPlacement(Form.Handle, @Where);
End;
Run Code Online (Sandbox Code Playgroud)