How can I make the main form align correctly after my control height is autosized and then I maximize the form?

757 Views Asked by At

This one I really don't know how to solve it...

How to reproduce the problem:

Run the code and and and shrink the window until the height of DriveBar is increased and then maximize the window. Then you can notice that Panel1 is no more top aligned, and between these two panels is an empty space. I tried to call Parent.Realign but with no succes. Can you please help me ?

UnitMain.pas

unit UnitMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ExtCtrls;

type

  TDriveBar = class(TCustomPanel)
  private
   procedure AutoHeight;
   procedure OnBarResize(Sender:TObject);
  public
   constructor Create(AOwner: TComponent); override;
   property Caption;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;
  Drives: TDriveBar;
  Panel1: TPanel;

implementation

{$R *.dfm}

//---------- TDriveBar --------------------------------

constructor TDriveBar.Create(AOwner: TComponent);
begin
 inherited;
 OnResize:=OnBarResize;
end;

procedure TDriveBar.OnBarResize(Sender: TObject);
begin
 AutoHeight;
 Parent.Realign;
end;

procedure TDriveBar.AutoHeight;
begin
 if Width<400 then Height:=100 else Height:=50;
end;

//---------- TForm1 -----------------------------------

procedure TForm1.FormCreate(Sender: TObject);
begin
  Drives:=TDriveBar.Create(Form1);
  Drives.Parent:=Form1;
  Drives.Caption:='DriveBar';
  Panel1:=TPanel.Create(Form1);
  Panel1.Parent:=Form1;
  Panel1.Caption:='Panel1';

  Panel1.Align:=alTop;
  Drives.Align:=alTop;
end;

end.

UnitMain.dfm

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 334
  ClientWidth = 618
  Color = clBtnFace
  DoubleBuffered = True
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
end
1

There are 1 best solutions below

1
On BEST ANSWER

First, never have a control handle its own event properties. Event properties are for the consumer of the component, not for the developer. The component developer's hook to the OnResize event is the protected Resize method. Override that if you want to know about OnResize-related events.

What I suspect is the source of your problem, however, is that you're changing the component's size from within the event that notifies that the size has changed. It's likely that this is being called from within the form's current attempt to move and size controls, and the form does what it can to avoid recursive realignment requests.

Instead, override the CanResize method. It's called with the proposed new size of the control. You can adjust the dimensions, or reject the resize entirely by returning False. Make sure to call the inherited method, too.

function TDriveBar.CanResize(var NewWidth, NewHeight: Integer): Boolean;
begin
  if NewWidth < 400 then NewHeight := 100 else NewHeight := 50;
  Result := inherited CanResize(NewWidth, NewHeight);
end;