nil
nil

Reputation: 1328

How to position a TForm poOwnerFormCenter when owner is MDI Child?

I would like to show TCustomForm descendants as dialogs so that they are positioned poOwnerFormCenter. But the same code that is positioning the form correctly when FormStyle is fsNormal does not set the correct position when FormStyle is fsMDIChild.

When the secondary form has FormStyle = fsNormal Button1 opens the modal dialog like this: fsNormal

But when the secondary form has FormStyle = fsMDIChild the positioning seems to be relative to the position of the MDI Child to the MDI Parent, not the absolute postion of the MDI Child: fsMDIChild

I'm not sure if I make any mistakes, if this is maybe a bug or normal behavior.

Following code is used to show the dialog:

procedure TForm3.Button1Click(Sender: TObject);
var
  AModalForm: TForm;
begin
  AModalForm := TForm.Create(Self);
  try
    AModalForm.Position := poOwnerFormCenter;
    AModalForm.ShowModal;
  finally
    AModalForm.Free;
  end;
end;

Project to reproduce:

dpr

program Project2;

uses
  Vcl.Forms,
  Unit2 in 'Unit2.pas' {Form2},
  Unit3 in 'Unit3.pas' {Form3};

{$R *.res}

var
  AMainForm: TForm2;
  A: TApplication;
begin
  A := Application;
  A.Initialize;
  A.MainFormOnTaskbar := True;
  A.CreateForm(TForm2, AMainForm);
  A.Run;
end.

Unit2

pas

unit Unit2;

interface

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

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

implementation

{$R *.dfm}

uses
  Unit3;

procedure TForm2.Button1Click(Sender: TObject);
var
  AForm: TForm3;
begin
  AForm := TForm3.Create(Self);
  AForm.FormStyle := fsMDIChild;
end;

procedure TForm2.Button2Click(Sender: TObject);
var
  AForm: TForm3;
begin
  AForm := TForm3.Create(Self);
  AForm.FormStyle := fsNormal;
end;

end.

dfm

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 356
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  FormStyle = fsMDIForm
  OldCreateOrder = False
  Visible = True
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 97
    Height = 356
    Align = alLeft
    TabOrder = 0
    object Button1: TButton
      Left = 8
      Top = 39
      Width = 75
      Height = 25
      Caption = 'fsMDIChild'
      TabOrder = 0
      OnClick = Button1Click
    end
    object Button2: TButton
      Left = 8
      Top = 8
      Width = 75
      Height = 25
      Caption = 'fsNormal'
      TabOrder = 1
      OnClick = Button2Click
    end
  end
end

Unit3

pas

unit Unit3;

interface

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

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

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  AModalForm: TForm;
begin
  AModalForm := TForm.Create(Self);
  try
    AModalForm.Position := poOwnerFormCenter;
    AModalForm.ShowModal;
  finally
    AModalForm.Free;
  end;
end;


end.

dfm

object Form3: TForm3
  Left = 0
  Top = 0
  Caption = 'Form3'
  ClientHeight = 336
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Visible = True
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 8
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
end

Upvotes: 3

Views: 1736

Answers (1)

Tom Brunberg
Tom Brunberg

Reputation: 21033

After trying several ideas found here on SO and also elsewhere, and all my attempts failing, I guess the safest (= working in all Delphi versions) solution is as follows.

Unit1 - Form1:TForm1 - fsMDIForm
Unit2 - Form2:TForm2 - fsMDIChild
Unit3 - AModalForm:TFom3 - ordinary form, shown modally, centered on the Form2

The essential part is simply a fallback to manually calculating and setting Left and Top properties of AModalForm so it becomes centered. It requies also setting Position property to poDesigned

// Showing the modal form centered by a fsMDIChild form
procedure TForm2.Button1Click(Sender: TObject);
var
  AModalForm: TForm3;
begin
  AModalForm := TForm3.Create(self);
  try
    AModalForm.Left := Self.ClientOrigin.X + (Self.ClientWidth-AModalForm.Width) div 2;
    AModalForm.Top  := Self.ClientOrigin.Y + (Self.ClientHeight-AModalForm.Height) div 2;
    AModalForm.Position := poDesigned;

    AModalForm.ShowModal;
    // use modalresult as needed
  finally
    AModalForm.Free;
  end;
end;

Upvotes: 2

Related Questions