You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi运行时如何计算TCategoryButtons控件的总高度?

运行时计算TCategoryButtons总高度的实现方法

TCategoryButtons的分类头高度和按钮高度虽未在公开属性中暴露,但可通过访问控件protected域方法或手动文本测量两种方式计算,结果可自动适配字体大小变化。


方法1:调用protected内置方法(推荐,适配所有默认/自定义样式)

VCL的TCategoryButtons类在protected域内置了GetCategoryHeight、GetButtonHeight方法,直接返回对应元素的实际像素高度,可通过类破解的方式调用:

// 定义破解类访问protected成员
type
  TCategoryButtonsHack = class(TCategoryButtons);

function CalcCategoryButtonsTotalHeight(ACategoryButtons: TCategoryButtons): Integer;
var
  I: Integer;
  LCategory: TCategoryButtonsCategory;
  LButtonHeight: Integer;
begin
  Result := 0;
  if not Assigned(ACategoryButtons) then Exit;

  // 获取统一的按钮高度
  LButtonHeight := TCategoryButtonsHack(ACategoryButtons).GetButtonHeight;

  // 遍历所有分类累加高度
  for I := 0 to ACategoryButtons.Categories.Count - 1 do
  begin
    LCategory := ACategoryButtons.Categories[I];
    // 累加当前分类头高度
    Result := Result + TCategoryButtonsHack(ACategoryButtons).GetCategoryHeight(LCategory);
    // 分类展开时累加下属所有按钮高度
    if LCategory.Expanded then
      Result := Result + LButtonHeight * LCategory.Items.Count;
    // 累加分类间默认间距(默认VCL样式下为4像素)
    Result := Result + 4;
  end;

  // 减去最后一个分类多余的末尾间距
  if Result > 4 then
    Result := Result - 4;
end;

该方法返回值会自动跟随控件Font属性、VCL样式变化,无需手动调整内边距参数。


方法2:手动文本测量(无需访问protected成员)

如果不想使用类破解方式,可通过控件Canvas测量文本高度加上固定内边距计算,默认Windows样式下误差小于1像素:

function CalcCategoryButtonsTotalHeightManual(ACategoryButtons: TCategoryButtons): Integer;
var
  I: Integer;
  LCategory: TCategoryButtonsCategory;
  LCategoryHeight, LButtonHeight: Integer;
begin
  Result := 0;
  if not Assigned(ACategoryButtons) then Exit;

  ACategoryButtons.Canvas.Font.Assign(ACategoryButtons.Font);
  // 分类头高度 = 文本高度 + 上下内边距共12像素
  LCategoryHeight := ACategoryButtons.Canvas.TextHeight('Qg') + 12;
  // 按钮高度 = 文本高度 + 上下内边距共8像素
  LButtonHeight := ACategoryButtons.Canvas.TextHeight('Qg') + 8;

  for I := 0 to ACategoryButtons.Categories.Count - 1 do
  begin
    LCategory := ACategoryButtons.Categories[I];
    Result := Result + LCategoryHeight;
    if LCategory.Expanded then
      Result := Result + LButtonHeight * LCategory.Items.Count;
    Result := Result + 4;
  end;

  if Result > 4 then
    Result := Result - 4;
end;

如果使用自定义VCL样式,只需对应调整代码中的内边距数值即可。


注意事项

  • 调用计算函数时需确保控件已完成窗口句柄创建,不要在窗体OnCreate事件中过早调用,建议放在OnShow或之后的生命周期节点执行,避免Canvas未初始化导致计算偏差。
  • 两种方法均已兼容分类折叠/展开状态的高度计算。

内容的提问来源于stack exchange,提问作者user1580348

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 15:51:03