Search code examples
delphivcldelphi-xe6

TPanel does not AutoSize when containing a TPanel


I have a panel inside another:

enter image description here

The inner panel is aligned alTop:

enter image description here

And the outer panel is set to AutoSize=true:

enter image description here

And everything sizes. If i changes the height of the inner panel at design time, the outer panel auto sizes to accommodate it:

enter image description here

And now runtime

Now i need to change the height of the inner panel at runtime:

procedure TForm2.Button1Click(Sender: TObject);
begin
    pnlInner.Height := pnlInner.Height + 50;
    lblPointer.Top := pnlOuter.Top + pnlInner.Height;
end;

Except when i change the height of the inner panel at runtime, the autosize panel does not autosize:

enter image description here

This of course worked in Delphi 5, 7, and probably XE2 - XE5.

What's the fix?

The workaround is, of course, to bypass Alignment/Autosize and do everything during various OnResize events. But that's distinctly not RAD. I'm sure it's a small bug in the VCL somewhere. And since we already have about two-dozen XE6 VCL bugs that we've patched, it would be better to fix it so nobody else has to think about it.

Bonus Chatter

I love the line:

and, could you please attach sample project?

It's almost as if nobody bothered to even try to reproduce it.


Solution

  • The issue is a regression in TWinControl.AlignControls:

    procedure TWinControl.AlignControls(AControl: TControl; var Rect: TRect);
    begin
       //...snip
    
       // Apply any constraints
       if Showing and ((sfWidth in FScalingFlags) or (sfHeight in FScalingFlags)) then
          DoAdjustSize;
    
       //...snip
    end;
    

    The bug here is that it will not call DoAdjustSize unless either sfWidth or sfHeight scaling flags are present.

    The fix is to not try to outsmart yourself, and DoAdjustSize regardless:

    procedure TWinControl.AlignControls(AControl: TControl; var Rect: TRect);
    begin
       //...snip
    
       // Apply any constraints
       //QC125995: Don't look to scaling flags to decide if we should adjust size
       if Showing {and ((sfWidth in FScalingFlags) or (sfHeight in FScalingFlags))} then
          DoAdjustSize;
    
       //...snip
    end;
    

    With this fix found, we're halfway to solving the similar issue except with a TOleControl (e.g. TWebBrowser) rather than a TPanel.

    Note: Any code released into public domain. No attribution required.