В дизайнере form1 я добавил элемент управления treeview и добавил к нему один корневой узел и один дочерний узел. И создал событие рисования.
В коде формы 1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AdvancedTreeView atv = new AdvancedTreeView();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
AdvancedTreeView.FillPolygonPoint(e);
}
}
}
Класс AdvancedTreeView:
using System;
using System.Drawing;
using System.Windows.Forms;
public class AdvancedTreeView : TreeView
{
private static Image myimage;
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawAll;
ShowLines = false;
AlternateBackColor = BackColor;
}
public Color AlternateBackColor { get; set; }
protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
e.DrawDefault = true;
base.OnDrawNode(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 Image GetIcon(bool isExpanded)
{
return myimage;
}
private int GetTopNodeIndex(TreeNode node)
{
while (node.Parent != null)
node = node.Parent;
return Nodes.IndexOf(node);
}
public static void FillPolygonPoint(PaintEventArgs e)
{
// Create solid brush.
SolidBrush blueBrush = new SolidBrush(Color.Blue);
// Create points that define polygon.
Point point1 = new Point(0, 0);
Point point2 = new Point(20, 10);
Point point3 = new Point(0, 20);
Point[] curvePoints = { point1 , point2, point3 };
// Draw polygon to screen.
e.Graphics.FillPolygon(blueBrush, curvePoints);
myimage = new Bitmap(10,10,e.Graphics);
}
}
Доходит до строки в AdvancedTreeView :
DrawMode = TreeViewDrawMode.OwnerDrawAll;
Но он никогда не попадает в OnDrawNode. Я также пробовал TreeViewDrawMode.OwnerDrawText, но он никогда не попадал в OnDrawNode.
🤔 А знаете ли вы, что...
C# обладает сборщиком мусора, который автоматически управляет памятью, что снижает риск утечек памяти.
Итак, вот более полная версия «оригинального» AdvancedTreeView
образца из старого ответа.
Новыми членами являются поля openedIcon
и closedIcon
, свойство ArrowColor
и методы GetIcon
/InitIcon
.
public class AdvancedTreeView : TreeView
{
private Bitmap openedIcon, closedIcon;
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawText;
ShowLines = false;
AlternateBackColor = BackColor;
ArrowColor = SystemColors.WindowText;
}
public Color AlternateBackColor { get; set; }
public Color ArrowColor { 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);
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);
}
private Image GetIcon(bool nodeIsExpanded)
{
if (openedIcon == null)
InitIcons();
return nodeIsExpanded ? openedIcon : closedIcon;
}
private void InitIcons()
{
openedIcon = new Bitmap(16, 16);
closedIcon = new Bitmap(16, 16);
using (Brush b = new SolidBrush(ArrowColor))
{
using (Graphics g = Graphics.FromImage(openedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 0), new Point(8, 15), });
using (Graphics g = Graphics.FromImage(closedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 8), new Point(0, 15), });
}
}
}
Designer после настройки цветов и добавления узлов:
Во время выполнения:
Его все еще можно улучшить, аннулируя цвета при их изменении и так далее...