VirtualTreeView - 同一节点中不同颜色的文本

Posted

技术标签:

【中文标题】VirtualTreeView - 同一节点中不同颜色的文本【英文标题】:VirtualTreeView - different color of text in the same node 【发布时间】:2015-02-01 05:27:48 【问题描述】:

我正在尝试在TVirtualStringTree 中创建一个类似于以下内容的视图:

在上面的示例中,我展示了我想要达到的一些可能的场景。 FolderA 有粗体文本,之后是同一节点中的红色非粗体文本。我正在寻找制作这种输出的方法。

但是,如果这太难或太难创建,我会很高兴 FolderBFolderC 类型的输出 - 可能有 2 列,一个包含文件夹名称,另一个包含里面的文件数。

FolderD 在这里只是一个没有文件的文件夹的示例以及该文件夹的输出(文本是非粗体并且没有数字)。

我正在寻找如何制作这种效果的任何方向,因为 VirtualTreeView 似乎每个节点只能有单一颜色或粗体设置。任何提示或建议如何向 FolderAFolderBFolderC 方向移动都非常感谢,所以我有一个起点。欢迎使用 Delphi 或 C++ Builder 示例(不过最终代码将在 C++ Builder 中)。

【问题讨论】:

您可以处理OnMeasureTextWidth 事件以提供整体文本宽度并在OnDrawText 事件处理程序中呈现这两个文本。但我个人会使用 2 列,这样用户可以随时看到计数。 @TLama 我同意 2 列确实有其优势,我很可能会在以后切换到该列。但此时我需要一个快速的解决方案,toShowStaticText 正是这样做的。很遗憾,我只能接受一个答案,因为您的两个答案都是很好的解决方案。 @TLama 好的,也许我不够清楚 - “文件夹 A”是首选,如果 A 不起作用,B 和 C 变体只是计划 B 或 C。 “快速”部分是我不需要引入一些额外的代码来处理列(不是 VirtualTree 代码,它确实相当简单,而是一些其他的额外内容)。我真的很感谢您提供的答案,如果您将其添加为附加答案,我肯定会支持它(我相信其他人也会更喜欢它而不是我的偏好,所以它肯定会得到更多的支持!)。 【参考方案1】:

您可以简单地使用toShowStaticText (StringOptions) 选项:

implementation

type
  PNodeRec = ^TNodeRec;
  TNodeRec = record
    Name: WideString;
    Count: Integer;
    IsBold: Boolean;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Node: PVirtualNode;
  NodeRec: PNodeRec;
  I: Integer;
begin
  VirtualStringTree1.TreeOptions.StringOptions := 
    VirtualStringTree1.TreeOptions.StringOptions + [toShowStaticText];
  VirtualStringTree1.NodeDataSize := Sizeof(TNodeRec);
  // Populate some data
  for I := 1 to 10 do
  begin
    Node := VirtualStringTree1.AddChild(nil);
    NodeRec := VirtualStringTree1.GetNodeData(Node);
    Initialize(NodeRec^);
    NodeRec.Name := 'Node' + IntToStr(I);
    NodeRec.Count := I;
    NodeRec.IsBold := I mod 2 = 0;
  end;
end;

procedure TForm1.VirtualStringTree1GetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
  NodeRec: PNodeRec;
begin
  NodeRec := PNodeRec(TVirtualStringTree(Sender).GetNodeData(Node));
  if TextType = ttNormal then
    CellText := NodeRec^.Name
  else // ttStatic
    CellText := Format('(%d)', [NodeRec^.Count]);
end;

procedure TForm1.VirtualStringTree1PaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  NodeRec: PNodeRec;
begin
  NodeRec := PNodeRec(TVirtualStringTree(Sender).GetNodeData(Node));
  if TextType = ttNormal then
  begin
    if NodeRec^.IsBold then
      TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsBold];
  end
  else // ttStatic
    TargetCanvas.Font.Color := clRed;
end;

输出:

【讨论】:

这太容易了!我刚刚试了一下,效果很好,谢谢一百万!我现在唯一的小问题是右侧的静态部分有点太多(比如一个额外的空间左右)。 ttStatic 的左边距(或ttNormal 的右边距)也可以调整吗? 我不知道有这样的内置功能(但我也在使用相当旧的 VT 版本)。您可以处理PaintText 事件上的绘图(而不是处理ttStaticGetText)。你有Canvas + TargetCanvas。随意放置文本。 + 你有TextMargin 属性。这将影响普通文本和静态文本。 当前版本的广告自定义文字绘制;不要在OnPaintText 事件中绘制(最多为那里的画布准备字体)。在OnDrawText 事件中绘制(不要忘记将DefaultDraw 设置为False)。除了您可能需要重新测量节点文本矩形(例如,OnMeasureTextWidth 事件中的宽度)以匹配您的可变字体设置和要呈现的文本(这就是我的答案)。

以上是关于VirtualTreeView - 同一节点中不同颜色的文本的主要内容,如果未能解决你的问题,请参考以下文章

从同一节点项目运行2个不同的容器

Cassandra 多个节点位于同一服务器上的不同数据中心

mysql ndb集群数据节点未同步且对同一查询的不同响应

XSLT 1.0 将同一级别的多个相同节点以不同的值分组

是否允许在 Mainline DHT 中的同一 ip:port 对后面运行多个不同的 DHT 节点?

使用另一个文件中同一节点的值替换节点值