You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 5中如何设置TVirtualNode内自定义面板的宽度

解决TVirtualStringTree自定义Panel宽度匹配节点的问题

核心修改思路

  1. 动态匹配节点宽度:通过树的事件获取节点实际显示区域,动态设置Panel的大小和位置,避免硬编码宽度。
  2. 同步滚动位置:处理树的滚动事件,确保Panel随节点一起移动。
  3. 优化内部控件布局:使用Align属性让Label和Button自动适应Panel大小。

具体代码修改

1. 添加树的事件处理

给TVirtualStringTree添加OnAfterItemPaint和OnScroll事件,用来更新Panel的位置和大小:

procedure Form.vstAfterItemPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
var
  NodeData: PTreeData;
  Panel: TMyPanel;
  Offset: TPoint;
begin
  NodeData := Sender.GetNodeData(Node);
  if Assigned(NodeData.Control) and (NodeData.Control is TMyPanel) then
  begin
    Panel := TMyPanel(NodeData.Control);
    // 计算控件位置:节点区域减去滚动偏移
    Offset := Sender.ScrollOffset;
    Panel.BoundsRect := Rect(
      ItemRect.Left - Offset.X,
      ItemRect.Top - Offset.Y,
      ItemRect.Right - Offset.X,
      ItemRect.Bottom - Offset.Y
    );
  end;
end;

procedure Form.vstScroll(Sender: TBaseVirtualTree);
var
  Node: PVirtualNode;
begin
  // 滚动时触发所有带控件的节点重绘,更新控件位置
  Node := Sender.GetFirst;
  while Assigned(Node) do
  begin
    Sender.InvalidateNode(Node);
    Node := Sender.GetNext(Node);
  end;
end;

2. 修改CreateNodeControl函数

移除硬编码的Width设置,让Panel高度匹配节点默认高度:

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;
  Height := Tree.DefaultNodeHeight; // 匹配节点高度
  Visible := true;
  Align := alNone; // 手动控制位置大小
 end;
 Tree.IsDisabled[Node] := True;
 Result := NodeData.Control;
end;

3. 调整FormCreate中的Panel设置

移除硬编码的Width和多余的Top设置,依赖Align属性布局内部控件:

MyPanel := TMyPanel(CreateNodeControl(vst, Node, TMyPanel));
with MyPanel do
begin
 Align := alNone;

 CName := TLabel.Create(MyPanel);
 CName.Align := alClient;
 Cname.Caption := 'test';
 Cname.Parent := MyPanel;

 Cstar := TSpeedButton.Create(MyPanel);
 Cstar.OnClick := onFavouriteClick;
 Cstar.Parent := MyPanel;
 Cstar.Align := alRight;
 Cstar.Flat := True;    
 TestBitmap := TBitmap.Create;
 try
    ImageList1.GetBitmap(4, TestBitmap);
    Cstar.Glyph.Assign(TestBitmap);
 finally
    TestBitmap.Free;
 end;
end;

4. 确保TreeData结构正确

确认你的TTreeData定义包含Control字段:

type
  PTreeData = ^TTreeData;
  TTreeData = record
    Text: WideString;
    Control: TControl;
  end;

关键说明

  • 不要将Panel的Parent设为nil:控件必须有父窗口(这里是vst)才能正常显示。
  • 避免硬编码Width:节点宽度会随树的列宽、窗口大小变化,动态获取ItemRect才能保证匹配。
  • 滚动同步:通过OnScroll触发节点重绘,确保Panel随节点滚动时位置正确。

内容的提问来源于stack exchange,提问作者mohammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:18:15