Search code examples
delphidelphi-5tvirtualstringtree

How to set width of a panel inside a virtual node in Delphi 5


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

image

What I want to achieve:

image

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;

Solution

  • After many hours, I found a way to solve the problem.

    You need to set the Right property of Rect inside the procedure setNodeControlVisible.

    result

    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;