【发布时间】:2017-03-22 14:30:18
【问题描述】:
【问题讨论】:
-
treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll; -
A recent question 在这里的答案有问题,所以我在那里发布了一个更完整的解决方案。
【问题讨论】:
treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll;
使用TreeViewDrawMode.OwnerDrawText 这样缩进将由TreeView 调整。除此之外,你应该实现完整的绘画。
public sealed class AdvancedTreeView : TreeView
{
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawText;
ShowLines = false;
AlternateBackColor = BackColor;
}
public Color AlternateBackColor { get; set; }
protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
// background
Color backColor = (GetTopNodeIndex(e.Node) & 1) == 0 ? BackColor : AlternateBackColor;
using (Brush b = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(b, new Rectangle(0, e.Bounds.Top, ClientSize.Width, e.Bounds.Height));
}
// icon
if (e.Node.Nodes.Count > 0)
{
Image icon = GetIcon(e.Node.IsExpanded); // TODO: true=down;false:right
e.Graphics.DrawImage(icon, e.Bounds.Left - icon.Width - 3, e.Bounds.Top);
}
// text (due to OwnerDrawText mode, indenting of e.Bounds will be correct)
TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, ForeColor);
// indicate selection (if not by backColor):
if ((e.State & TreeNodeStates.Selected) != 0)
ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds);
}
private int GetTopNodeIndex(TreeNode node)
{
while (node.Parent != null)
node = node.Parent;
return Nodes.IndexOf(node);
}
}
要获得与屏幕截图相似的结果,只需设置颜色即可。
advancedTreeView1.BackColor = Color.DeepSkyBlue;
advancedTreeView1.AlternateBackColor = Color.LightBlue;
【讨论】:
AdvancedTreeView,添加了 10 个带有子节点的节点(之前使用标准 TreeView 进行了测试),但它只显示背景颜色为 DeepSkyBlue。我在OnDrawNode添加了一个断点,这个函数永远不会被调用。
DrawMode 不是Normal,则调用它。
GetIcon。现在三角形绘制好了,我们可以定义颜色和边距。我认为它更可重用。
只需在 TreeView 的属性中将 DrawMode 设置为“OwnerDrawAll”即可。但请记住,您必须自己绘制它并且必须处理 TreeView_DrawNode 事件。以下是事件处理的示例:
private void TreeListView_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (e.Bounds.Height == 0)
return;
e.Graphics.FillRectangle(new SolidBrush((e.Node.Parent?.Index ?? e.Node.Index) % 2 == 0 ? Color.Blue : Color.Aqua), e.Bounds);
if (e.Node.Nodes.Count > 0)
{
if (!e.Node.IsExpanded)
e.Graphics.FillPolygon(Brushes.Red,
new[]
{
new PointF(e.Bounds.X + e.Bounds.Height / 10, e.Bounds.Y + e.Bounds.Height / 10),
new PointF(e.Bounds.X + e.Bounds.Height / 10, e.Bounds.Y + e.Bounds.Height * 0.9f),
new PointF(e.Bounds.X + e.Bounds.Height, e.Bounds.Y + e.Bounds.Height / 2)
});
else
e.Graphics.FillPolygon(Brushes.Red,
new[]
{
new PointF(e.Bounds.X + e.Bounds.Height / 10, e.Bounds.Y + e.Bounds.Height / 10),
new PointF(e.Bounds.X + e.Bounds.Height, e.Bounds.Y + e.Bounds.Height / 10),
new PointF(e.Bounds.X + e.Bounds.Height / 2, e.Bounds.Y + e.Bounds.Height)
});
}
e.Graphics.DrawString(e.Node.Text, new Font(FontFamily.GenericMonospace, e.Bounds.Height * 0.7f),
new SolidBrush(Color.Black),
new Rectangle(e.Bounds.X + e.Bounds.Height, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));
}
【讨论】:
TextRenderer.DrawText和e.Graphics.DrawString有区别吗?