3

I'm experiencing a weird issue when I set "DPI Awareness" mode in the project options to "GDI Scaling" with a secondary form, where, if I set its BorderStyle to bsNone and change its position while the Main form is on another monitor with different DPI scaling, the coordinates (within Monitor 1) are completely off. Let me explain my case and how to reproduce more clearly:

My setup (Windows 11)

  • Monitor 1: 1920x1080, 100% scale (DPI)
  • Monitor 3: 4K TV, cloned with Monitor 1
  • Monitor 2: 1920x1200, 150% scale (DPI), to the right of Monitor 1

Case 1: I create Form2 (bsSizeable), Form1 is in either Monitor, I change Form2's position -> OK
Case 2: I create Form2 (bsNone), Form1 is in Monitor 1, I change Form2's position -> OK
Case 3: I create Form2 (bsNone), -move Form1 to Monitor 2-, then change Form2's position -> the position is completely wrong.

"Per Monitor v2" -> OK in all cases (different, unrelated issues, however)
"GDI Scaling" + bsSizeable (Form2) -> OK
"GDI Scaling" + bsNone (Form2) -> wrong position

Case 1 Case 2 Case 3

DPR

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2},
  Vcl.Themes,
  Vcl.Styles;

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit 1

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Application);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Form2.Left := Screen.PrimaryMonitor.WorkareaRect.Left + 300;
  Form2.Top  := Screen.PrimaryMonitor.WorkareaRect.Top  + 300;
  Form1.Caption := Form2.Left.ToString + ' - ' + Form2.Top.ToString;
end;

end.

Form 1

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 312
  ClientWidth = 296
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  Position = poScreenCenter
  TextHeight = 15
  object Button1: TButton
    Left = 8
    Top = 8
    Width = 185
    Height = 121
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 8
    Top = 135
    Width = 185
    Height = 114
    Caption = 'Button2'
    TabOrder = 1
    OnClick = Button2Click
  end
end

Unit 2

unit Unit2;

interface

uses
  Winapi.Windows, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, ShellApi,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
  TForm2 = class(TForm)
    Label1: TLabel;
  private
    procedure CreateParams(var Params : TCreateParams);  override;
  public
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.CreateParams(var Params : TCreateParams);
begin
  inherited CreateParams(Params);
  With Params do begin
    ExStyle   := ExStyle or WS_EX_TOPMOST;
    WndParent := GetDesktopwindow;
  end;
end;

end.

Form 2

object Form2: TForm2
  Left = 100
  Top = 100
  AlphaBlendValue = 200
  BorderStyle = bsNone
  Caption = 'Form2'
  ClientHeight = 95
  ClientWidth = 201
  Color = 4227327
  TransparentColorValue = clGreen
  DefaultMonitor = dmPrimary
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  FormStyle = fsStayOnTop
  Position = poScreenCenter
  Visible = True
  TextHeight = 15
  object Label1: TLabel
    Left = 8
    Top = 8
    Width = 142
    Height = 37
    Caption = 'Hello World'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -27
    Font.Name = 'Segoe UI'
    Font.Style = []
    ParentFont = False
  end
end

enter image description here

hikari
  • 3,393
  • 1
  • 33
  • 72
  • `Form2.Left := Screen.PrimaryMonitor.WorkareaRect.Left + 300;` looks suspicious - positions the form based on the work area of the Primary Monitor when it's on another monitor. – Brian Apr 18 '23 at 14:28
  • The primary monitor is always the same, no matter where the form is, but changing that to a fixed position has the same results. – hikari Apr 18 '23 at 14:59

0 Answers0