Winform TreeView 实现 Win7 Areo效果

新建一个继承自TreeView的控件类,代码如下:

  1. using System;  
  2. using System.Windows.Forms;  
  3. using System.Drawing;  
  4. using System.Runtime.InteropServices;  
  5.   
  6. namespace SenseTreeView  
  7. {  
  8.     public class SenseTreeView : TreeView  
  9.     {  
  10.         #region 控件属性   
  11.   
  12.         //显示字体   
  13.         private Font _NodeFont;  
  14.         public Font NodeFont  
  15.         {  
  16.             get  
  17.             {  
  18.                 return _NodeFont;  
  19.             }  
  20.             set  
  21.             {  
  22.                 _NodeFont = value;  
  23.             }  
  24.         }  
  25.   
  26.         //选择TreeView TreeNode时的背景色   
  27.         private Brush _BackgrountBrush;  
  28.         public Brush BackgroundBrush  
  29.         {  
  30.             get  
  31.             {  
  32.                 return _BackgrountBrush;  
  33.             }  
  34.             set  
  35.             {  
  36.                 _BackgrountBrush = value;  
  37.             }  
  38.         }  
  39.   
  40.         //选择TreeView TreeNode时背景色的边框画笔   
  41.         private Pen _BackgroundPen;  
  42.         public Pen BackgroundPen  
  43.         {  
  44.             get  
  45.             {  
  46.                 return _BackgroundPen;  
  47.             }  
  48.             set  
  49.             {  
  50.                 _BackgroundPen = value;  
  51.             }  
  52.         }  
  53.   
  54.         //TreeView中TreeNode展开时的节点显示图标,   
  55.         private Image _NodeExpandedImage;  
  56.         public Image NodeExpandedImage  
  57.         {  
  58.             get  
  59.             {  
  60.                 return _NodeExpandedImage;  
  61.             }  
  62.             set  
  63.             {  
  64.                 _NodeExpandedImage = value;  
  65.             }  
  66.         }  
  67.         //TreeView中TreeNode合拢时的节点显示图标   
  68.         private Image _NodeCollapseImage;  
  69.         public Image NodeCollapseImage  
  70.         {  
  71.             get  
  72.             {  
  73.                 return _NodeCollapseImage;  
  74.             }  
  75.             set  
  76.             {  
  77.                 _NodeCollapseImage = value;  
  78.             }  
  79.         }  
  80.         //TreeView中TreeNode的节点显示图标的大小   
  81.         private Size _NodeImageSize;  
  82.         public Size NodeImageSize  
  83.         {  
  84.             get  
  85.             {  
  86.                 return _NodeImageSize;  
  87.             }  
  88.             set  
  89.             {  
  90.                 _NodeImageSize = value;  
  91.             }  
  92.         }  
  93.   
  94.         //节点显示图标离左边界的位置   
  95.         private int _NodeOffset;  
  96.         public int NodeOffset  
  97.         {  
  98.             get  
  99.             {  
  100.                 return _NodeOffset;  
  101.             }  
  102.             set  
  103.             {  
  104.                 _NodeOffset = value;  
  105.             }  
  106.         }  
  107.  
  108.         #endregion  
  109.  
  110.         #region 构造函数   
  111.   
  112.         public SenseTreeView()  
  113.         {  
  114.             //设置窗体Style   
  115.             //this.SetStyle(ControlStyles.UserPaint, true);               //支持用户重绘窗体   
  116.             //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);    //在内存中先绘制界面   
  117.             //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);   //双缓冲,防止绘制时抖动   
  118.             //this.SetStyle(ControlStyles.DoubleBuffer, true);            //双缓冲,防止绘制时抖动    
  119.             //this.UpdateStyles();   
  120.   
  121.             //不显示树形节点显示连接线   
  122.             this.ShowLines = false;  
  123.   
  124.             //设置绘制TreeNode的模式   
  125.             this.DrawMode = TreeViewDrawMode.OwnerDrawAll;  
  126.   
  127.             //不显示TreeNode前的“+”和“-”按钮   
  128.             this.ShowPlusMinus = false;  
  129.   
  130.             //不支持CheckedBox   
  131.             this.CheckBoxes = false;  
  132.   
  133.             //设置TreeNode的行高   
  134.             SendMessage(this.Handle, TVM_SETITEMHEIGHT, 20, 0);  
  135.   
  136.             //设置默认BackgroundBrush   
  137.             BackgroundBrush = new SolidBrush(Color.FromArgb(90, Color.FromArgb(205, 226, 252)));  
  138.   
  139.             //设置默认BackgroundPen   
  140.             BackgroundPen = new Pen(Color.FromArgb(130, 249, 252), 1);  
  141.   
  142.             //设置默认NodeFont   
  143.             NodeFont = new Font("宋体", 12, FontStyle.Regular);  
  144.   
  145.             //设置默认节点显示图标及Size   
  146.             NodeExpandedImage = null;  
  147.             NodeCollapseImage = null;  
  148.             NodeImageSize = new Size(18, 18);  
  149.   
  150.             //设置默认节点显示图标便宜位置   
  151.             NodeOffset = 5;  
  152.         }  
  153.  
  154.         #endregion  
  155.  
  156.         #region 节点绘制函数   
  157.   
  158.         //绘制TreeView树中TreeNode   
  159.         protected override void OnDrawNode(DrawTreeNodeEventArgs e)  
  160.         {  
  161.             TreeNode tn = e.Node as TreeNode;  
  162.             if (tn == null)  
  163.             {  
  164.                 return;  
  165.             }  
  166.   
  167.             //设置Image绘制Rectangle   
  168.             Point pt = new Point(tn.Bounds.X + NodeOffset, tn.Bounds.Y);  
  169.             Rectangle rt = new Rectangle(pt, NodeImageSize);  
  170.   
  171.             if ((e.State & TreeNodeStates.Selected) != 0)  
  172.             {  
  173.                 //绘制TreeNode选择后的背景框   
  174.                 e.Graphics.FillRectangle(BackgroundBrush, 2, tn.Bounds.Y, this.Width - 7, tn.Bounds.Height - 1);  
  175.   
  176.                 //绘制TreeNode选择后的边框线条   
  177.                 e.Graphics.DrawRectangle(BackgroundPen, 1, tn.Bounds.Y, this.Width - 6, tn.Bounds.Height - 1);                                  
  178.             }  
  179.   
  180.             //绘制节点图片   
  181.             if (NodeExpandedImage != null && NodeCollapseImage != null)  
  182.             {  
  183.                 if (tn.Nodes.Count != 0)  
  184.                 {  
  185.                     if (tn.IsExpanded == true)  
  186.                     {  
  187.                         e.Graphics.DrawImage(NodeExpandedImage, rt);  
  188.                     }  
  189.                     else  
  190.                     {  
  191.                         e.Graphics.DrawImage(NodeCollapseImage, rt);  
  192.                     }  
  193.                 }  
  194.   
  195.                 rt.X += 15;  
  196.             }  
  197.   
  198.             //绘制节点自身图片                   
  199.             if (e.Node.SelectedImageIndex != -1 && this.ImageList != null)  
  200.             {  
  201.                 rt.X += 5;  
  202.                 e.Graphics.DrawImage(this.ImageList.Images[e.Node.SelectedImageIndex], rt);  
  203.             }  
  204.   
  205.             //绘制节点的文本   
  206.             rt.X += 20;  
  207.             rt.Y += 1;  
  208.             rt.Width = this.Width - rt.X;  
  209.             e.Graphics.DrawString(e.Node.Text, NodeFont, Brushes.Black, rt);  
  210.         }  
  211.  
  212.         #endregion  
  213.  
  214.         #region 鼠标消息响应函数   
  215.   
  216.         //响应鼠标按下消息   
  217.         protected override void OnMouseDown(MouseEventArgs e)  
  218.         {  
  219.             TreeNode clickedNode = this.GetNodeAt(e.X, e.Y);  
  220.   
  221.             if (clickedNode != null && NodeBounds(clickedNode).Contains(e.X, e.Y))  
  222.             {  
  223.                 this.SelectedNode = clickedNode;                  
  224.             }  
  225.         }  
  226.   
  227.         //响应鼠标双击消息   
  228.         protected override void OnMouseDoubleClick(MouseEventArgs e)  
  229.         {  
  230.             TreeNode clickedNode = this.GetNodeAt(e.X, e.Y);  
  231.   
  232.             if (clickedNode != null && NodeBounds(clickedNode).Contains(e.X, e.Y))  
  233.             {  
  234.                 this.SelectedNode = clickedNode;  
  235.   
  236.                 //判断节点的状态   
  237.                 if (clickedNode.Nodes.Count != 0)  
  238.                 {  
  239.                     if (clickedNode.IsExpanded)  
  240.                     {  
  241.                         clickedNode.Collapse();  
  242.                     }  
  243.                     else  
  244.                     {  
  245.                         clickedNode.Expand();  
  246.                     }  
  247.                 }  
  248.             }  
  249.         }  
  250.  
  251.         #endregion  
  252.  
  253.         #region 私有函数   
  254.   
  255.         //返回TreeView中TreeNode的整行区域   
  256.         private Rectangle NodeBounds(TreeNode node)  
  257.         {  
  258.             // Set the return value to the normal node bounds.   
  259.             Rectangle bounds = node.Bounds;  
  260.   
  261.             //if (node.Tag != null)   
  262.             //{   
  263.             //    // Retrieve a Graphics object from the TreeView handle   
  264.             //    // and use it to calculate the display width of the tag.   
  265.             //    Graphics g = this.CreateGraphics();   
  266.             //    int tagWidth = (int)g.MeasureString(node.Tag.ToString(), NodeFont).Width + 6;   
  267.   
  268.             //    // Adjust the node bounds using the calculated value.   
  269.             //    bounds.Offset(tagWidth / 2, 0);   
  270.             //    bounds = Rectangle.Inflate(bounds, tagWidth / 2, 0);   
  271.             //    g.Dispose();   
  272.             //}   
  273.   
  274.             bounds.Width = this.Width;  
  275.   
  276.             return bounds;  
  277.         }  
  278.  
  279.         #endregion  
  280.  
  281.         #region 引用函数   
  282.   
  283.         const int TV_FRIST = 0x1100;  
  284.         const int TVM_SETITEMHEIGHT = TV_FRIST + 27;  
  285.   
  286.         [DllImport("user32.dll", CharSet = CharSet.Auto)]  
  287.         private static extern IntPtr SendMessage(IntPtr hWnd, int nMsg, int wParam, int Param);  
  288.  
  289.         #endregion   
  290.     }  
  291. }  
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
    }
}

调用代码:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8. using SenseTreeView.Properties;  
  9.   
  10. namespace SenseTreeView  
  11. {  
  12.     public partial class Form1 : Form  
  13.     {  
  14.         private SenseTreeView stv;  
  15.   
  16.         public Form1()  
  17.         {  
  18.             InitializeComponent();  
  19.   
  20.             // Create and initialize the TreeView control.   
  21.             stv = new SenseTreeView();  
  22.             stv.Dock = DockStyle.Left;  
  23.             stv.BackColor = Color.White;  
  24.             //stv.CheckBoxes = true;   
  25.             stv.Width = 250;  
  26.   
  27.             ImageList imagelist = new ImageList();  
  28.             imagelist.Images.Add(Resources._1264);  
  29.             imagelist.Images.Add(Resources._1265);  
  30.             imagelist.Images.Add(Resources._1268);  
  31.             stv.ImageList = imagelist;  
  32.   
  33.             stv.NodeExpandedImage = Resources.UnSelect;  
  34.             stv.NodeCollapseImage = Resources.IsSelect;  
  35.   
  36.             // Add nodes to the TreeView control.               
  37.             for (int x = 1; x < 4; ++x)  
  38.             {  
  39.                 // Add a root node to the TreeView control.                   
  40.                 TreeNode node = new TreeNode("中华人民共和国");  
  41.                 node.SelectedImageIndex = 0;  
  42.                 for (int y = 1; y < 4; ++y)  
  43.                 {  
  44.                     // Add a child node to the root node.   
  45.                     TreeNode tn = new TreeNode("Subtask");  
  46.                     tn.SelectedImageIndex = 2;  
  47.                     node.Nodes.Add(tn);  
  48.                 }  
  49.                 stv.Nodes.Add(node);  
  50.             }  
  51.             stv.ExpandAll();  
  52.   
  53.             // Initialize the form and add the TreeView control to it.               
  54.             this.Controls.Add(stv);  
  55.         }  
  56.     }  
  57. }  
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);
        }
    }
}

效果图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值