Search code examples
delphivcldelphi-10.4-sydney

How to calculate the height of a TCategoryButtons at run-time?


In a Delphi 10.4.2 VCL Application in Windows 10, how can I calculate the height of a TCategoryButtons object at run-time, i.e. the sum of all its button heights and its Category items, as this height could vary depending on its font size?

Measuring the pixel heights at run-time, I have noticed that all buttons have the same height and that the buttons have a different height as the Category items.

Also, note that the buttons do not have a published Height property in the Object Inspector.

But shouldn't it be possible to calculate the sum of all its button heights and its Category items with some low-level methods?


Solution

  • This is a control entirely implemented in Pascal, in Vcl.CategoryButtons.pas.

    Therefore, you can see exactly how it is implemented. For instance, in TCategoryButtons.Paint you see its complete drawing code. Similarly, you can investigate the hit testing done in MouseMove (or MouseDown or MouseUp).

    Consequently, if nothing else, you can create your own modified version of TCategoryButtons using this code. Your version can save the total height when it has been determined (for instance, certainly after painting).

    However, after a quick look, it seems like TButtonCategory.Bounds might be interesting. If you are lucky, this returns the on-screen rect of a category. The Bottom of the last category's rect should be the (effectively used) height of the entire control.

    It seems to work for me:

    Screen recording of a TCategoryButtons control being used (categories colapsed and expanded, buttons moved between categories). As the controls effectively used height varies, a red bar's height is updated accordingly.

    Here I draw a red bar of the same height as the control.

    procedure TForm5.FormPaint(Sender: TObject);
    begin
      var y := CategoryButtons1.Categories[
        CategoryButtons1.Categories.Count - 1
      ].Bounds.Bottom;
      Canvas.Brush.Color := clRed;
      Canvas.FillRect(Rect(0, 0, ClientWidth, y))
    end;