效果圖:
新建一個繼承自TreeView的控件類,代碼如下:
using System; using System.Windows.Forms; using System.Drawing; using System.Runtime.InteropServices; namespace SenseTreeView { public class SenseTreeView : TreeView { #region 控件屬性 //顯示字體 private Font _NodeFont; public Font NodeFont { get { return _NodeFont; } set { _NodeFont = value; } } //選擇TreeView TreeNode時的背景色 private Brush _BackgrountBrush; public Brush BackgroundBrush { get { return _BackgrountBrush; } set { _BackgrountBrush = value; } } //選擇TreeView TreeNode時背景色的邊框畫筆 private Pen _BackgroundPen; public Pen BackgroundPen { get { return _BackgroundPen; } set { _BackgroundPen = value; } } //TreeView中TreeNode展開時的節點顯示圖標, private Image _NodeExpandedImage; public Image NodeExpandedImage { get { return _NodeExpandedImage; } set { _NodeExpandedImage = value; } } //TreeView中TreeNode合攏時的節點顯示圖標 private Image _NodeCollapseImage; public Image NodeCollapseImage { get { return _NodeCollapseImage; } set { _NodeCollapseImage = value; } } //TreeView中TreeNode的節點顯示圖標的大小 private Size _NodeImageSize; public Size NodeImageSize { get { return _NodeImageSize; } set { _NodeImageSize = value; } } //節點顯示圖標離左邊界的位置 private int _NodeOffset; public int NodeOffset { get { return _NodeOffset; } set { _NodeOffset = value; } } #endregion #region 構造函數 public SenseTreeView() { //設置窗體Style //this.SetStyle(ControlStyles.UserPaint, true); //支持用戶重繪窗體 //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); //在內存中先繪制界面 //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); //雙緩沖,防止繪制時抖動 //this.SetStyle(ControlStyles.DoubleBuffer, true); //雙緩沖,防止繪制時抖動 //this.UpdateStyles(); //不顯示樹形節點顯示連接線 this.ShowLines = false; //設置繪制TreeNode的模式 this.DrawMode = TreeViewDrawMode.OwnerDrawAll; //不顯示TreeNode前的“+”和“-”按鈕 this.ShowPlusMinus = false; //不支持CheckedBox this.CheckBoxes = false; //設置TreeNode的行高 SendMessage(this.Handle, TVM_SETITEMHEIGHT, 20, 0); //設置默認BackgroundBrush BackgroundBrush = new SolidBrush(Color.FromArgb(90, Color.FromArgb(205, 226, 252))); //設置默認BackgroundPen BackgroundPen = new Pen(Color.FromArgb(130, 249, 252), 1); //設置默認NodeFont NodeFont = new Font("宋體", 12, FontStyle.Regular); //設置默認節點顯示圖標及Size NodeExpandedImage = null; NodeCollapseImage = null; NodeImageSize = new Size(18, 18); //設置默認節點顯示圖標便宜位置 NodeOffset = 5; } #endregion #region 節點繪制函數 //繪制TreeView樹中TreeNode protected override void OnDrawNode(DrawTreeNodeEventArgs e) { TreeNode tn = e.Node as TreeNode; if (tn == null) { return; } //設置Image繪制Rectangle Point pt = new Point(tn.Bounds.X + NodeOffset, tn.Bounds.Y); Rectangle rt = new Rectangle(pt, NodeImageSize); if ((e.State & TreeNodeStates.Selected) != 0) { //繪制TreeNode選擇后的背景框 e.Graphics.FillRectangle(BackgroundBrush, 2, tn.Bounds.Y, this.Width - 7, tn.Bounds.Height - 1); //繪制TreeNode選擇后的邊框線條 e.Graphics.DrawRectangle(BackgroundPen, 1, tn.Bounds.Y, this.Width - 6, tn.Bounds.Height - 1); } //繪制節點圖片 if (NodeExpandedImage != null && NodeCollapseImage != null) { if (tn.Nodes.Count != 0) { if (tn.IsExpanded == true) { e.Graphics.DrawImage(NodeExpandedImage, rt); } else { e.Graphics.DrawImage(NodeCollapseImage, rt); } } rt.X += 15; } //繪制節點自身圖片 if (e.Node.SelectedImageIndex != -1 && this.ImageList != null) { rt.X += 5; e.Graphics.DrawImage(this.ImageList.Images[e.Node.SelectedImageIndex], rt); } //繪制節點的文本 rt.X += 20; rt.Y += 1; rt.Width = this.Width - rt.X; e.Graphics.DrawString(e.Node.Text, NodeFont, Brushes.Black, rt); } #endregion #region 鼠標消息響應函數 //響應鼠標按下消息 protected override void OnMouseDown(MouseEventArgs e) { TreeNode clickedNode = this.GetNodeAt(e.X, e.Y); if (clickedNode != null && NodeBounds(clickedNode).Contains(e.X, e.Y)) { this.SelectedNode = clickedNode; } } //響應鼠標雙擊消息 protected override void OnMouseDoubleClick(MouseEventArgs e) { TreeNode clickedNode = this.GetNodeAt(e.X, e.Y); if (clickedNode != null && NodeBounds(clickedNode).Contains(e.X, e.Y)) { this.SelectedNode = clickedNode; //判斷節點的狀態 if (clickedNode.Nodes.Count != 0) { if (clickedNode.IsExpanded) { clickedNode.Collapse(); } else { clickedNode.Expand(); } } } } #endregion #region 私有函數 //返回TreeView中TreeNode的整行區域 private Rectangle NodeBounds(TreeNode node) { // Set the return value to the normal node bounds. Rectangle bounds = node.Bounds; //if (node.Tag != null) //{ // // Retrieve a Graphics object from the TreeView handle // // and use it to calculate the display width of the tag. // Graphics g = this.CreateGraphics(); // int tagWidth = (int)g.MeasureString(node.Tag.ToString(), NodeFont).Width + 6; // // Adjust the node bounds using the calculated value. // bounds.Offset(tagWidth / 2, 0); // bounds = Rectangle.Inflate(bounds, tagWidth / 2, 0); // g.Dispose(); //} bounds.Width = this.Width; return bounds; } #endregion #region 引用函數 const int TV_FRIST = 0x1100; const int TVM_SETITEMHEIGHT = TV_FRIST + 27; [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int nMsg, int wParam, int Param); #endregion } }
在窗體里應用:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using SenseTreeView.Properties; namespace SenseTreeView { public partial class Form1 : Form { private SenseTreeView stv; public Form1() { InitializeComponent(); // Create and initialize the TreeView control. stv = new SenseTreeView(); stv.Dock = DockStyle.Left; stv.BackColor = Color.White; //stv.CheckBoxes = true; stv.Width = 250; ImageList imagelist = new ImageList(); imagelist.Images.Add(Resources._1264); imagelist.Images.Add(Resources._1265); imagelist.Images.Add(Resources._1268); stv.ImageList = imagelist; stv.NodeExpandedImage = Resources.UnSelect; stv.NodeCollapseImage = Resources.IsSelect; // Add nodes to the TreeView control. for (int x = 1; x < 4; ++x) { // Add a root node to the TreeView control. TreeNode node = new TreeNode("中華人民共和國"); node.SelectedImageIndex = 0; for (int y = 1; y < 4; ++y) { // Add a child node to the root node. TreeNode tn = new TreeNode("Subtask"); tn.SelectedImageIndex = 2; node.Nodes.Add(tn); } stv.Nodes.Add(node); } stv.ExpandAll(); // Initialize the form and add the TreeView control to it. this.Controls.Add(stv); } } }