Jump to content
Sign in to follow this  

autosize columns in VirtualStringTree in grid mode

Recommended Posts

I have got a VirtualStringTree in grid mode and I would like to autosize the columns so that they are wide enough to display the column text and the column header.


Calling vst.Header.AutoFitColumns works for the column text but not for the header.



I would have thought that this question has been asked and answerted before, but my Google fu is becoming ever weaker. I found lots of hints on how to fit the column text, but not the header.

Share this post

Link to post

Since apparently nobody has ans answer and I was unable to find any settings or method to achieve this, here is the code I used:

procedure TMyForm.ResizeTree(_vst: TVirtualStringTree);
  c: UInt32;
  ws: WideString;
  cnv: TCanvas;
  Fnt: TFont;
  ThisWidth: UInt32;
  MinWidth: UInt32;
  Node: PVirtualNode;
  r: TRect;
  s: TSize;
  cnv := _vst.Canvas;
  for c := 0 to _vst.Header.Columns.Count - 1 do begin
    ws := _vst.Header.Columns[c].Text;
    GetTextExtentPoint32W(cnv.Handle, PWideChar(ws), Length(ws), s);
    MinWidth := s.cx + 10;
    Fnt := _vst.Font;
    Node := _vst.RootNode.FirstChild;
    while Assigned(Node) do begin
      _vst.GetTextInfo(Node, c, Fnt, r, ws);
      ThisWidth := r.Right - r.Left + 10;
      if MinWidth < ThisWidth then
        MinWidth := ThisWidth;
      Node := Node.NextSibling;
    _vst.Header.Columns[c].Width := MinWidth;

It's probably not perfect but it worked for me (until I dropped the VirtualStringTree because it just added too much complexity for what I wanted to achieve, and replaced it with the much simpler TdzVirtualTreeView which I had to extend for my use case.) I particular I don't like the constant 10 pixels in the code.

Share this post

Link to post

I customized function TBaseVirtualTree.GetMaxColumnWidth that is used in AutoFitColumns - what I use to autosize columns:


// start with Column Caption width
if FHeader.FColumns[Column].Text <> '' then
      GetTextExtentPoint32W(Canvas.Handle, PWideChar(FHeader.FColumns[Column].Text), Length(FHeader.FColumns[Column].Text), vSize);
      Result := vSize.cx + 20; // Margin


Which takes into account the Column caption and adds it to the starting Result value, before it gets to calculating column width based on text.


I put it before this line:

while Assigned(Run) and not OperationCanceled do


Works good for my usage.

Share this post

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this