如何在 TVirtualStringTree 中自动调整跨列的大小?

How to auto size spanned column in TVirtualStringTree?

我有一个简单的 VirtualStringTree (VST) 示例,它有 4 列,在第 2 或第 3 列中我可以有更多适合默认列宽的文本。我启用了 hoAutoSpanColumns,因此如果其他列为空,大文本将与其他列重叠。这很好用。问题是第 2 列或第 3 列中的文本应该跨越 VST 的全长。在这种情况下,大列仅延伸到最后(第 4)列的末尾。

下面是第 3 行的第 2 列如何仅跨越第 3 和第 4 列,然后停在第 4 列的宽度处:

如果我使用 AutoFitColumns 自动调整第 2 列的大小:

VST1.Header.AutoFitColumns(false, smaUseColumnOption,1,1);

然后它推入第 3 和第 4 列,因此它们从第 2 列的末尾开始:

但我需要第 3 列和第 4 列保持相同的位置,如下所示:

有没有办法让第 2 列自动适合文本,但让第 3 和第 4 列保持在原来的位置?

目前没有 built-in 自动适应 header 跨栏文本的方法。要自动调整给定列的大小以查看整个跨文本,您可以编写这样的代码(对于单个节点)。请注意 VT 中的自动跨度功能目前不支持 RTL 读取(因此此代码也不支持):

type
  TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
  protected
    function GetSpanColumn(Node: PVirtualNode): TColumnIndex; virtual;
  public
    procedure AutoFitSpanColumn(DestColumn: TColumnIndex; Node: PVirtualNode);
  end;

implementation

{ TVirtualStringTree }

function TVirtualStringTree.GetSpanColumn(Node: PVirtualNode): TColumnIndex;
begin
  { this returns visible span column for the given node, InvalidColumn otherwise }
  Result := Header.Columns.GetLastVisibleColumn;
  while ColumnIsEmpty(Node, Result) and (Result <> InvalidColumn) do
    Result := Header.Columns.GetPreviousVisibleColumn(Result);
end;

procedure TVirtualStringTree.AutoFitSpanColumn(DestColumn: TColumnIndex; Node: PVirtualNode);
var
  ColsWidth: Integer;
  SpanWidth: Integer;
  SpanOffset: Integer;
  SpanColumn: TColumnIndex;
begin
  SpanColumn := GetSpanColumn(Node);

  if SpanColumn <> InvalidColumn then
  begin
    { get the total width of the header }
    ColsWidth := Header.Columns.TotalWidth;
    { get the width of the span text cell as it would be autosized }
    SpanWidth := DoGetNodeWidth(Node, SpanColumn) + DoGetNodeExtraWidth(Node, SpanColumn) +
      DoGetCellContentMargin(Node, SpanColumn).X + Margin;
    { and get the left position of the span cell column in header }
    SpanOffset := Header.Columns[SpanColumn].GetRect.Left;
    { now, the width of the autosized column we increase by the subtraction of the fully
      visible span cell width and all columns width increased by offset of the span cell
      column; in other words, we'll just increase or decrease width of the DestColumn to
      the difference of width needed for the span column to be fully visible, or "fit" }
    Header.Columns[DestColumn].Width := Header.Columns[DestColumn].Width +
      SpanWidth - ColsWidth + SpanOffset;
  end;
end;