VirtualTreeView - 同一节点中不同颜色的文本
Posted
技术标签:
【中文标题】VirtualTreeView - 同一节点中不同颜色的文本【英文标题】:VirtualTreeView - different color of text in the same node 【发布时间】:2015-02-01 05:27:48 【问题描述】:我正在尝试在TVirtualStringTree
中创建一个类似于以下内容的视图:
在上面的示例中,我展示了我想要达到的一些可能的场景。 FolderA 有粗体文本,之后是同一节点中的红色非粗体文本。我正在寻找制作这种输出的方法。
但是,如果这太难或太难创建,我会很高兴 FolderB 或 FolderC 类型的输出 - 可能有 2 列,一个包含文件夹名称,另一个包含里面的文件数。
FolderD 在这里只是一个没有文件的文件夹的示例以及该文件夹的输出(文本是非粗体并且没有数字)。
我正在寻找如何制作这种效果的任何方向,因为 VirtualTreeView 似乎每个节点只能有单一颜色或粗体设置。任何提示或建议如何向 FolderA 或 FolderB 或 FolderC 方向移动都非常感谢,所以我有一个起点。欢迎使用 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
事件上的绘图(而不是处理ttStatic
的GetText
)。你有Canvas
+ TargetCanvas
。随意放置文本。
+ 你有TextMargin
属性。这将影响普通文本和静态文本。
当前版本的广告自定义文字绘制;不要在OnPaintText
事件中绘制(最多为那里的画布准备字体)。在OnDrawText
事件中绘制(不要忘记将DefaultDraw
设置为False)。除了您可能需要重新测量节点文本矩形(例如,OnMeasureTextWidth
事件中的宽度)以匹配您的可变字体设置和要呈现的文本(这就是我的答案)。以上是关于VirtualTreeView - 同一节点中不同颜色的文本的主要内容,如果未能解决你的问题,请参考以下文章