TPanel does not AutoSize when containing a TPanel

2019-05-01 12:10发布

问题:

I have a panel inside another:

The inner panel is aligned alTop:

And the outer panel is set to AutoSize=true:

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

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:

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.

回答1:

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.



回答2:

This is reported in Embarcaderos Quality Central:

  • QC125995: [Regression in XE6 Update1] TPanel.AutoSize is not working
  • QC129330: AutoSize property is not always applied

I can reproduce this with XE6, but not with XE7.