I have a descendant of TVirtualStringTree
class with my own autosizing columns procedure. To make it work whenever the size of the control is changed I have overriden the Resize
procedure:
type
TMyVirtualStringTree = class(TVirtualStringTree)
protected
procedure Resize; override;
end;
.....
procedure TMyVirtualStringTree.Resize;
var
cb: Integer;
begin
inherited;
if Header.Columns.Count > 0 then
for cb := 0 to Header.Columns.Count - 1 do
Header.Columns[cb].Width := round((Width - 20) / Header.Columns.Count);
end;
Everything works fine except one thing: resizing columns manually (by mouse on the header) without changing actual size of the control causes generation of unwanted WM_SIZE
events with different LParams (control size). And thus Resize
is called and columns automatically adjust their width which I didn't mean them to. How to make autosize work only when the control width is actually changed?
You can add a Boolean flag FColumnResize
, which you set to True
in the DoColumnResize
method.
In the Resize
method check for the flag i.e:
type
TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
protected
FColumnResize: Boolean;
procedure Resize; override;
procedure DoColumnResize(Column: TColumnIndex); override;
end;
...
procedure TVirtualStringTree.DoColumnResize(Column: TColumnIndex);
begin
inherited;
FColumnResize := True;
end;
procedure TVirtualStringTree.Resize;
var
cb: Integer;
begin
inherited;
if not FColumnResize then
begin
Header.Columns.BeginUpdate; { Important: do not trigger OnColumnResize }
try
if Header.Columns.Count > 0 then
for cb := 0 to Header.Columns.Count - 1 do
Header.Columns[cb].Width := round((Width - 20) / Header.Columns.Count);
finally
Header.Columns.EndUpdate;
end;
end;
FColumnResize := False;
end;
Another option instead of overriding DoColumnResize
it is probably better to override and set FColumnResize
to True
in DoHeaderMouseDown
, and back to False
in DoHeaderMouseUp
. in that case remove the FColumnResize := False
in the Resize
method.