For my project in the company, I need to implement a TVirtualStringTree
with its nodes holding custom controls. Meaning they are holding not only a text control, but for example a panel with labels and buttons.
I have found a solution for a similar problem here:
VirtualTreeView embedding button in the cells
Which really helps, but I want to get that custom panel inside the TVirtualNode
to have the same width as its parent TVirtualNode
.
What I tried until now is setting the width of TMyPanel
with some value and setting its parent to nil
, which meant that TMyPanel
would not be shown in the TVirtualNode
.
Does anyone have an idea or solution how to get the width of the panel smaller?
Panel which its width is bigger then its parent
What I want to achieve:
TMyPanel = class(TPanel)
public
Cstar: TSpeedButton;
CName: TLabel;
CImageIndex : Integer;
end;
procedure Form.FormCreate(Sender: TObject);
var
NodeData: ^TTreeData;
Node: PVirtualNode;
MyPanel: TMyPanel;
TestBitmap: TBitmap;
begin
inherited;
vst.NodeDataSize := SizeOf(TTreeData);
vst.ScrollBarOptions.ScrollBars := ssVertical;
vst.NodeDataSize := SizeOf(TTreeData);
Node := vst.AddChild(nil);
InitializeNodeData(vst, Node, 'Vertrieb');
Node := vst.AddChild(Node);
InitializeNodeData(vst,Node, 'TMyPanel');
MyPanel := TMyPanel(CreateNodeControl(vst, Node, TMyPanel));
with MyPanel do
begin
// Caption := 'TMyPanel';
// Color := vst.Color;
// BevelOuter := bvNone;
// BevelInner := bvNone;
// ClientWidth := 10;
Width := 40;
// left := 0;
Align := alNone;
CName := TLabel.Create(MyPanel);
CName.Align := alClient;
Cname.Caption := 'test';
Cname.Top := 0;
Cname.Parent := MyPanel;
Cstar := TSpeedButton.Create(MyPanel);
Cstar.OnClick := onFavouriteClick;
Cstar.Parent := MyPanel;
Cstar.Top := 0;
Cstar.Align := AlRight;
Cstar.Flat := True;
TestBitmap := TBitmap.Create;
try
ImageList1.GetBitmap(4, TestBitmap);
Cstar.Glyph.Assign(TestBitmap);
finally
TestBitmap.Free;
end;
end;
end;
function Form.CreateNodeControl(Tree: TVirtualStringTree; Node:PVirtualNode;ControlClass: TControlClass): TControl;
var
NodeData: PTreeData;
begin
NodeData := Tree.GetNodeData(Node);
NodeData.Control := ControlClass.Create(Tree);
with NodeData.Control do
begin
Parent := vst;
Width := 10;
// Height := Tree.DefaultNodeHeight;
width:= 10;
// Align := alRight;
Visible := true;
end;
Tree.IsDisabled[Node] := True;
Result := NodeData.Control;
end;
procedure Form.InitializeNodeData(Tree: TVirtualStringTree;Node: PVirtualNode; const Text: WideString);
var
NodeData: PTreeData;
begin
NodeData := Tree.GetNodeData(Node);
Initialize(NodeData^);
NodeData.Text := Text;
end;
After many hours, I found a way to solve the problem.
You need to set the Right
property of Rect
inside the procedure setNodeControlVisible
.
Go to this question:
VirtualTreeView embedding button in the cells
And replace the procedure with the code provided below:
procedure Form.SetNodeControlVisible(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex = NoColumn);
var
NodeData: PTreeData;
R: TRect;
begin
NodeData := Tree.GetNodeData(Node);
if Assigned(NodeData) and Assigned(NodeData.Control) then
begin
with NodeData.Control do
begin
Visible := IsNodeVisibleInClientRect(Tree, Node, Column)
and ((Node.Parent = Tree.RootNode) or (vsExpanded in Node.Parent.States));
R := Tree.GetDisplayRect(Node, Column, true);
R.Right := Tree.ClientWidth ;
BoundsRect := R;
end;
end;
end;