2

In a Delphi 10.4.2 32-bit Delphi VCL Application, I have a TLabel set on top of a TCard:

object lblColorTransparencyInfo: TLabel
  AlignWithMargins = True
  Left = 5
  Top = 37
  Width = 156
  Height = 20
  Margins.Left = 5
  Margins.Top = 5
  Margins.Right = 5
  Margins.Bottom = 5
  Align = alTop
  Caption = 
    'Pick a color in the image to make that color transparent in the ' +
    'whole image'
  Color = clInfoBk
  ParentColor = False
  Transparent = False
  WordWrap = True
  ExplicitTop = 0
end

Label.Color is set to clInfoBk, so you can visually check the Label's size.

However, despite the Label.AutoSize is set to True, the Label's HEIGHT is much higher than its text height, despite Label.AutoSize = True:

enter image description here

Is this a bug in TLabel.AutoSize?

How can I set the Label Height to its correct text-height? (Please note that the Label's width could dynamically change during run-time which would also dynamically change the text-height at run-time).

user1580348
  • 5,721
  • 4
  • 43
  • 105
  • Actually, `AutoSize` partly works for me even with `alTop`. Try to change the `Caption` (a lot: 5 rows, 2 rows, 7 rows, ...) using the OI. But if the container is resized, the height isn't updated. – Andreas Rejbrand Mar 31 '21 at 20:02
  • What do you mean by "partly"? - I have now changed it to more text but the Label height has increased even more: https://i.imgur.com/FoI4S7R.png – user1580348 Mar 31 '21 at 20:14
  • If I set a label to `Align = alTop`, `WordWrap = True`, and `AutoSize = True` and change the `Caption`, the height is correctly updated: https://privat.rejbrand.se/autosizelabeltop.gif However, resizing the container doesn't update the label's height correctly: https://privat.rejbrand.se/autosizelabelresize.gif – Andreas Rejbrand Mar 31 '21 at 20:18
  • In any case, this isn't a bug in `AutoSize`, since the [documentation](http://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.StdCtrls.TCustomLabel.AutoSize) says "When AutoSize is True, the size of the label readjusts whenever the text changes. The size of the label is also readjusts [sic!] when the Font property changes." – Andreas Rejbrand Mar 31 '21 at 20:28
  • Despite `Label.AutoSize = True` I can resize it with the mouse at design-time: https://i.imgur.com/uHLWWsR.gif Do you update `Label.Caption` at run-time? – user1580348 Mar 31 '21 at 20:30
  • No, I used the Object Inspector at design time. Yes, but if you change the `Caption`, doesn't its height autofit? – Andreas Rejbrand Mar 31 '21 at 20:30
  • With an interposer class and `procedure TLabel.Resize; begin inherited; AdjustBounds; end;` I can make it almost work. Quick and dirty: https://privat.rejbrand.se/autosizelabelresize2.gif – Andreas Rejbrand Mar 31 '21 at 20:33
  • Just to answer your previous question: When I change the Label.Caption at design-time then it auto-fits perfectly. But at RUN-TIME, the Label.Height stays always the same: https://i.imgur.com/0RZA3FT.gif – user1580348 Mar 31 '21 at 20:39
  • But in that GIF you don't change the `Caption`, but the container size. And that indeed doesn't work, as I wrote in my first comment. And in my comment 6 mins ago, I offered a solution to that issue. (Note: The "caption" is the text.) – Andreas Rejbrand Mar 31 '21 at 20:40
  • In fact, this has been observed before: https://stackoverflow.com/questions/25105663/resizing-label-does-not-change-label-height?rq=1 – Andreas Rejbrand Mar 31 '21 at 20:42
  • But in your last gif you even also update the container width at run-time. Will try the interposer trick. – user1580348 Mar 31 '21 at 20:43
  • Yes. If I resize the container without the interposer trick, the height isn't updated. The purpose of the interposer trick is to change that. In my third comment I show that it doesn't work by default (https://privat.rejbrand.se/autosizelabelresize.gif) and in my last comment I show that it does work with the interposer: https://privat.rejbrand.se/autosizelabelresize2.gif – Andreas Rejbrand Mar 31 '21 at 20:44
  • Now I have implemented the interposer trick: https://i.imgur.com/s8QV1Vj.png Is that correct? Btw, now it works, i.e. the height is correctly updated at run-time. Please write that in an answer, so I can accept it. Thank you! – user1580348 Mar 31 '21 at 21:34
  • Yes, that was exactly what I meant. – Andreas Rejbrand Mar 31 '21 at 21:35

1 Answers1

4

This is taken from the documentation for the TCustomLabel.AutoSize property:

When AutoSize is False, the label is fixed in size. When AutoSize is True, the size of the label readjusts whenever the text changes. The size of the label is also readjusts [sic] when the Font property changes.

When WordWrap is True, the width of the label is fixed. If AutoSize is also True, changes to the text cause the label to change in height. When AutoSize is True and WordWrap is False, the font determines the height of the label, and changes to the text cause the label to change in width.

It only promises to change the size when the text or font is changed -- not when the label is resized due to its parent being resized. So one could argue that there is no bug here:

Screen recording of alTop label resizing due to its caption being changed.

Screen recording of alTop label failing to resize due to parent resizing.

But in any case, one very quick and dirty solution is to tell the label to autosize when it is resized. Using an interposer class,

type
  TLabel = class(Vcl.StdCtrls.TLabel)
  protected
    procedure Resize; override;
  end;

implementation

{ TLabel }

procedure TLabel.Resize;
begin
  inherited;
  AdjustBounds;
end;

we can make it work (almost):

alTop label autosizing when the parent is resized

Of course, you could make your own TLabelEx control with this addition so you can use it as easily as the standard label.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • What do you mean by "almost"? – user1580348 Mar 31 '21 at 21:52
  • You can see that the label's width is also autofitted: the yellow background ends where the text ends, and not at the desired margin. Of course, this is only visible because we have changed the background from transparent to yellow. By default, a label is transparent. – Andreas Rejbrand Mar 31 '21 at 21:54
  • Could that lead to adding a `Padding` property to `TLabel`? Because that is one of the big shortcomings of `TLabel`: Not having a `Padding` property. – user1580348 Mar 31 '21 at 22:01
  • It wouldn't be difficult for Embarcadero to add more properties to the label control. For now, if you need padding, you can use margins instead or the parent's padding. (And make sure the parent has the right bg colour.) – Andreas Rejbrand Mar 31 '21 at 22:04
  • Yes, I can have FAKE PADDING by putting the Label on a `TPanel` with the same color, setting the Panel's `AutoSize = True` and the Label's `AlignWithMargins = True`. But it would be nice if `TLabel` had a `Padding` property. – user1580348 Mar 31 '21 at 22:13
  • 1
    I wish Embarcadero had you as Chief Developer! – user1580348 Mar 31 '21 at 22:40
  • I have added a small modification to avoid side-effects with "normal" Labels in an existing complex VCL Application: https://i.imgur.com/NJYhskb.png This restricts the interposer modification to Labels with an explicit `Tag`. – user1580348 Apr 01 '21 at 09:08
  • @user1580348: Yes, that is a common way to quickly restrict a modification to only some objects. The proper way, of course, it to create a new control and register it so it ends up in the Component Palette. – Andreas Rejbrand Apr 01 '21 at 09:37
  • If I make more modifications to `TLabel` then I will create a new component. – user1580348 Apr 01 '21 at 09:41