Winform绘制TreeView树形结构


创建组件:ZHTestTreeView

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ZHERP.UI.ZHControl
{
    public partial class ZHTestTreeView : TreeView
    {

        private bool ArrowKeyUp = false;
        private bool ArrowKeyDown = false;
        private Font foreFont = new Font("微软雅黑", 9F, FontStyle.Regular);
        /*1节点被选中 ,TreeView有焦点*/
        private SolidBrush brush1 = new SolidBrush(Color.FromArgb(229, 243, 251));//填充颜色
        private Pen pen1 = new Pen(Color.FromArgb(102, 167, 232), 1);//边框颜色

        /*2节点被选中 ,TreeView没有焦点*/
        private SolidBrush brush2 = new SolidBrush(Color.FromArgb(229, 243, 251));
        private Pen pen2 = new Pen(Color.FromArgb(222, 222, 222), 1);

        /*3 MouseMove的时候 画光标所在的节点的背景*/
        private SolidBrush brush3 = new SolidBrush(Color.FromArgb(229, 243, 251));
        private Pen pen3 = new Pen(Color.FromArgb(112, 192, 231), 1);

        //public const int WM_PRINTCLIENT = 0x0318;
        //public const int PRF_CLIENT = 0x00000004;
        
        public ZHTestTreeView()
        {
            //双缓存防止屏幕抖动
            //this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
            this.UpdateStyles();
            this.DrawMode = TreeViewDrawMode.OwnerDrawAll;
            this.FullRowSelect = true;
            this.HotTracking = true;
            this.HideSelection = false;
            this.ShowLines = false;
            this.ShowNodeToolTips = true;
            this.ItemHeight = 30;
        }
        public ZHTestTreeView(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }
        protected override void OnDrawNode(DrawTreeNodeEventArgs e)
        {
            base.OnDrawNode(e);
           


            #region 1     选中的节点背景=========================================
            Rectangle nodeRect = new Rectangle(0, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
           
            if (e.Node.IsSelected)
            {
                if (this.Focused)
                {
                    e.Graphics.FillRectangle(brush1, nodeRect);
                    // e.Graphics.DrawRectangle(pen1, nodeRect);边框
                }
                else
                {
                    e.Graphics.FillRectangle(brush2, nodeRect);
                    //e.Graphics.DrawRectangle(pen2, nodeRect);
                }

            }
            else if ((e.State & TreeNodeStates.Hot) != 0 && e.Node.Text != "")//|| currentMouseMoveNode == e.Node)
            {
                e.Graphics.FillRectangle(brush3, nodeRect);
                //e.Graphics.DrawRectangle(pen3, nodeRect);
            }
            else
            {
                e.Graphics.FillRectangle(Brushes.White, e.Bounds);
            }

            #endregion

            #region 2     +-号绘制=========================================
            Rectangle plusRect = new Rectangle(e.Node.Bounds.Left - 20, nodeRect.Top + 8, 13, 13); // +-号的大小 是9 * 9

            if (e.Node.IsExpanded)
                e.Graphics.DrawImage(Image.FromFile(Application.StartupPath + "\\Resources\\IconDown.png"), plusRect);
            else if (e.Node.IsExpanded == false && e.Node.Nodes.Count > 0)
                e.Graphics.DrawImage(Image.FromFile(Application.StartupPath + "\\Resources\\IconRight.png"), plusRect);
            #endregion

            #region 3     画节点文本=========================================
            Rectangle nodeTextRect = new Rectangle(
                                                    e.Node.Bounds.Left-6,
                                                    e.Node.Bounds.Top + 6,
                                                    e.Node.Bounds.Width + 2,
                                                    e.Node.Bounds.Height
                                                    );
            nodeTextRect.Width += 4;
            nodeTextRect.Height -= 4;

            e.Graphics.DrawString(e.Node.Text,
                                 foreFont,
                                  new SolidBrush(Color.Black),
                                  nodeTextRect);

            //画子节点个数 (111)
            //if (e.Node.GetNodeCount(true) > 0)
            //{
            //    e.Graphics.DrawString(string.Format("({0})", e.Node.GetNodeCount(true)),
            //                           foreFont,
            //                            Brushes.Gray,
            //                            nodeTextRect.Right - 4,
            //                            nodeTextRect.Top - 2);
            //}
            #endregion
        }
        protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
        {
            base.OnBeforeSelect(e);
            if (e.Node != null)
            {
                //禁止选中空白项
                if (e.Node.Text == "")
                {
                    //响应上下键
                    if (ArrowKeyUp)
                    {
                        if (e.Node.PrevNode != null && e.Node.PrevNode.Text != "")
                            this.SelectedNode = e.Node.PrevNode;
                    }
                    if (ArrowKeyDown)
                    {
                        if (e.Node.NextNode != null && e.Node.NextNode.Text != "")
                            this.SelectedNode = e.Node.NextNode;
                    }
                    e.Cancel = true;
                }
            }
        }


        /// <summary>
        /// 防止在选择设,treeNode闪屏
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                if (!DesignMode)
                {
                    cp.ExStyle |= 0x02000000;// Turn on WS_EX_COMPOSITED 
                }
                return cp;

            }
        }
        
    }
}

创建窗体页面Form2,在窗体设计器中拖入当前树形组件即可,代码内包装好树形数据和相应的点击事件

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;
using ZH.BLL.system;
using ZHERP.Models.DModels;

namespace ZHERP.UI.SM
{
    public partial class Form2 : Form
    {
        private MenuManage menuManage = new MenuManage();
        public Form2()
        {
            InitializeComponent();
            List<MenuInfoModel> menuList = menuManage.GetMenuList(new List<int>());
            GenerateUiTreeView(menuList, null, 0);
        }

        private void zhTreeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {

        }
        /// <summary>
        /// 生成树型菜单
        /// </summary>
        /// <param name="menuList"></param>
        /// <param name="node"></param>
        /// <param name="pId"></param>
        private void GenerateUiTreeView(List<MenuInfoModel> menuList, TreeNode node, int pId)
        {
            //获取所有子菜单列表
            var childList = menuList.Where(m => m.ParentId == pId);
            foreach (var child in childList)
            {
                TreeNode newNode = new TreeNode();
                newNode.Name = child.MId.ToString();
                newNode.Text = child.MName;
                newNode.Tag = child.HasChild;
                if (node != null)
                {
                    node.Nodes.Add(newNode);
                }
                else
                {
                    this.zhTestTreeView1.Nodes.Add(newNode);
                }
                GenerateUiTreeView(menuList, newNode, child.MId);
            }
        }
        /// <summary>
        /// 点击节点事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void zhTestTreeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Bounds.Contains(e.Location))
            {
                string parentId = "";
                parentId = e.Node.Name.ToString() != "0" ? e.Node.Name.ToString() : "";
                MsgBoxHelper.MsgBoxShow("提示", parentId);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/wgb0409/article/details/132604296