1
votes

How do you get the label height to automatically adjust when resizing the form? All of the properties are set. Align is top. Autosize is true. Word wrap is true.

When I change the form size the label adjust the caption fine. However, the actual label will not resize its height.

This leaves a gap when the form width is increasing or it leaves the bottom part of the caption unreadable. Makes it ugly when you have controls below the label that should move up or down depending on the label's height.

I would hate to do this using the form's resize event. Too bad there is no form "resize end" event.

Any help? Thanks.

2
OnResize is "resize end", I think you want WM_EXITSIZEMOVE.Sertac Akyuz
Consider using the label's Ancbors property. You can anchor the bottom of the label so it moves with its Parent's height changes.Remy Lebeau
To Sertac. According to my observations resize fires on every pixel change.t j
To Remy. Changing a top align label to include the bottom anchor does not work constantly - very very erratic.t j
@tj - It fires after the form has been resized. It can fire consecutively if "show window contents while dragging" is active, because with every pixel change the form has been resized. Consider searching on the message I commented.Sertac Akyuz

2 Answers

1
votes

If I recall correctly, with Autosize set to true, the height of the label is automatically set to the actual height of the text in Caption.

You might try setting Autosize to false and see how that works for you.

0
votes

I've solved by inheriting from tlabel. there is a bug with the autosize in this case (autosize, wordwrap and alTop)

to make it recalculate it size you need to:

AutoSize := false;
AutoSize := true;

so you can override the resize procedure like that:

procedure TResizableLabel.Resize;
begin
  AutoSize := false;
  AutoSize := true;
end;

however if you will do it on every resize it will shrink the width also, so you will lose the width of the parent from alTop, in case it is just aligned left it will probably be ok, but if you want center or right alignment you will need a better solution.

this is the full solution, it will call the autosize only when needed:

TResizableLaber = class(TLabel)
  protected
    FTextHeight, FTextWidth : integer;
    function GetCaption : TCaption;
    procedure SetCaption(ACaption : TCaption);
    function GetFont : TFont;
    procedure SetFont(AFont : TFont);
  public
    procedure Resize; override;
    property Caption : TCaption read GetCaption write SetCaption;
    property Font : TFont read GetFont write SetFont;
end;

implementation 

procedure TResizableLaber.Resize;
var
  num : double;
begin
  inherited;
  if AutoSize then
    begin
      if (FTextHeight = 0) or (FTextWidth = 0) then
        begin
            //lazy evaluation, we re evaluate every time the caption or font changes
            FTextWidth := Utills.GetTextWidth(Caption, Font);
            FTextHeight := Utills.GetTextHeight(Caption,Font);
        end;

      //TODO: there is still one bug here, set alCenter and make the last word long enough so it cant always wrapped to the line before, even though there is globally enough space
      num := (  Height / FTextHeight) - (FTextWidth /Width );
      //if num is greater then 1 it means we need an extra line, if it is lower then zero it means there is an extra line
      if (num > 1) or (num < 0) then
        begin
          //just doing this all the time will cause it to really resize and will break alTop matching the whole space
          AutoSize := false;
          AutoSize := true;
        end;
    end;
end;

function TResizableLaber.GetCaption : TCaption;
begin
  Result := inherited Caption;
end;
procedure TResizableLaber.SetCaption(ACaption : TCaption);
begin
  FTextWidth := Utills.GetTextWidth(ACaption, Self.Font);
  FTextHeight := Utills.GetTextHeight(ACaption,Self.Font);
  inherited Caption := ACaption;
end;

function TResizableLaber.GetFont : TFont;
begin
  Result := inherited Font;
end;
procedure TResizableLaber.SetFont(AFont : TFont);
begin
  FTextWidth := Utills.GetTextWidth(Caption, AFont);
  FTextHeight := Utills.GetTextHeight(Caption,AFont);
  inherited Font := AFont;
end;


class function Utills.GetTextHeight(const Text:String; Font:TFont) : Integer;
var
  bitmap: TBitmap;
begin
  bitmap := TBitmap.Create;
  try
   bitmap.Canvas.Font := Font;
   Result := bitmap.Canvas.TextHeight(Text);
  finally
   bitmap.Free;
  end;
end;

class function Utills.GetTextWidth(const Text:String; Font:TFont) : Integer;
var
  bitmap: TBitmap;
begin
  bitmap := TBitmap.Create;
  try
   bitmap.Canvas.Font := Font;
   Result := bitmap.Canvas.TextWidth(Text);
  finally
   bitmap.Free;
  end;
end;