Search code examples
delphialignmentanchor

Anchors [akLeft, akRight, akBottom] not working properly


I have a small problem with anchors.

I have a form with 2 panels, Panel1 is aligned to left and Panel2 is on the first, not aligned but anchored top and bottom. On the second panel there are two edits, they are anchored left, right and bottom only. This design causes a "minimizing" sliding effect whereby the edits disappear at the top when the form is resized. This is intended.

On the start of the application, the initial state of the second panel should be invisible, thus I use Panel2.Height := 0.

But after resizing the form, or manually setting Panel2.Height := 104, the edits are not dragged down to their anchored positions, but they remain invisible beyond the panel.

This is the sample code which could help to visualize it:

// unit 1
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TMoveEvent = procedure (Sender: TObject; X, Y: Integer) of object;

  TLabeledEdit = class(ExtCtrls.TLabeledEdit)
  private
    FOnMove: TMoveEvent;
    procedure WMMove(var Message: TWMMove); message WM_MOVE;
  public
    property OnMove: TMoveEvent read FOnMove write FOnMove;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    procedure LE1Move(Sender: TObject; X, Y: Integer);
    procedure LE2Move(Sender: TObject; X, Y: Integer);
  public
    procedure AfterConstruction; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  TypInfo;

const
  MaxSet = 255; // Largest ordinal value in a Delphi set.

type
  TSet = set of 0..MaxSet;

function SetToString(Info: PTypeInfo; const Value; const Separator, Prefix, Suffix: string): String; overload;
var
  CompInfo: PTypeInfo;
  CompData: PTypeData;
  SetValue: TSet absolute Value;
  Element: 0..MaxSet;
begin
  CompInfo:=GetTypeData(Info)^.CompType^;
  CompData:=GetTypeData(CompInfo);
  Result:='';
  for Element:=CompData.MinValue to CompData.MaxValue do begin
    if Element in SetValue then
      if Result = '' then
        Result := Prefix + GetEnumName(CompInfo, Element)
      else
        Result := Result + Separator + GetEnumName(CompInfo, Element);
  end;
  if Result = '' then
    Result := Prefix + Suffix
  else
    Result := Result + Suffix;
end;

function SetToString(Info: PTypeInfo; const Value; const Separator: string): String; overload;
begin
  Result:=SetToString(Info, Value, Separator, '[', ']');
end;

function SetToString(Info: PTypeInfo; const Value): String; overload;
begin
  Result:=SetToString(Info, Value, ', ');
end;

{ TLabeledEdit }

procedure TLabeledEdit.WMMove(var Message: TWMMove);
begin
  inherited;
  if Assigned(FOnMove) then
    FOnMove(Self, Message.XPos, Message.YPos);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  LabeledEdit1.OnMove:=LE1Move;
  LabeledEdit2.OnMove:=LE2Move;
end;

procedure TForm1.AfterConstruction;
begin
  inherited;
  Panel2.Height:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel2.Height:=0;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Panel2.Height:=104;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ShowMessage('LE1 Anchors = ' + SetToString(TypeInfo(TAnchors), LabeledEdit1.Anchors));
  ShowMessage('LE2 Anchors = ' + SetToString(TypeInfo(TAnchors), LabeledEdit2.Anchors));
end;

procedure TForm1.LE1Move(Sender: TObject; X, Y: Integer);
begin
  Label1.Caption:=Format('LE1 pos: %d : %d', [X, Y]);
end;

procedure TForm1.LE2Move(Sender: TObject; X, Y: Integer);
begin
  Label2.Caption:=Format('LE2 pos: %d : %d', [X, Y]);
end;

end.

// dfm
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 304
  ClientWidth = 643
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 200
    Top = 56
    Width = 31
    Height = 13
    Caption = 'Label1'
  end
  object Label2: TLabel
    Left = 200
    Top = 96
    Width = 31
    Height = 13
    Caption = 'Label2'
  end
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 185
    Height = 304
    Align = alLeft
    TabOrder = 0
    ExplicitLeft = 152
    ExplicitTop = 96
    ExplicitHeight = 41
    DesignSize = (
      185
      304)
    object Panel2: TPanel
      Left = 1
      Top = 81
      Width = 183
      Height = 104
      Anchors = [akLeft, akTop, akRight, akBottom]
      Constraints.MaxHeight = 104
      TabOrder = 0
      DesignSize = (
        183
        104)
      object LabeledEdit1: TLabeledEdit
        Left = 8
        Top = 24
        Width = 121
        Height = 21
        Anchors = [akLeft, akRight, akBottom]
        EditLabel.Width = 61
        EditLabel.Height = 13
        EditLabel.Caption = 'LabeledEdit1'
        TabOrder = 0
      end
      object LabeledEdit2: TLabeledEdit
        Left = 48
        Top = 72
        Width = 121
        Height = 21
        Anchors = [akLeft, akRight, akBottom]
        EditLabel.Width = 61
        EditLabel.Height = 13
        EditLabel.Caption = 'LabeledEdit2'
        TabOrder = 1
      end
    end
  end
  object Button1: TButton
    Left = 200
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Hide'
    TabOrder = 1
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 281
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Show'
    TabOrder = 2
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 200
    Top = 140
    Width = 75
    Height = 25
    Caption = 'Anchors'
    TabOrder = 3
    OnClick = Button3Click
  end
end

If Panel2.Height is not set to 0 after form create, the edits moves up and down when form is resized. If Panel2.Height is set to 0 on form create, the edits stay invisible out of the Panel2, and if Panel2 is shown, they stay invisible whereby the Top positions are negative.

Can anybody help?


Solution

  • Two possible solutions:

    1. Set Panel2's height to zero in the form's OnShow event instead of in AfterConstruction, or
    2. Place another panel on Panel2 with Align=alBottom.

    Exactly why the first solution does work I don't know, but it certainly has merit, because during OnCreate (or AfterConstruction as you use), the windowed control handles aren't allocated yet.