using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using Lskj.Main.Properties; using System.Runtime.InteropServices; namespace Lskj.Main.main2 { /// /// description: 自定义树 /// author: gyc /// date: 2017-03-16 /// public partial class TreeViewCustom : UserControl { #region 公有属性 /// /// 父节点字段 /// public string ParentField; /// /// 显示节点文本字段 /// public string TextField; /// /// 父节点关联子节点位数 /// public int ParentKeyLength; public delegate void ButtonClickEventHandler(Button after); #endregion #region 私有属性 /// /// 上次显示节点 /// private string lastTreeNode; /// /// 上次显示按钮ID /// private string lastMenuId; /// 数据源 /// private DataTable dataSource; private ButtonClickEventHandler clickEvent; /// /// 缓存菜单,按照节点缓存 /// private Dictionary> dicTreeNodes = new Dictionary>(); /// /// 缓存所有按钮 /// private Dictionary dicButtons = new Dictionary(); #endregion #region Api [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam); private const int WM_SETREDRAW = 11; /// /// 停止界面重绘 /// /// public static void SuspendDrawing(Control parent) { SendMessage(parent.Handle, WM_SETREDRAW, false, 0); } /// /// 开始绘制 /// /// public static void ResumeDrawing(Control parent) { SendMessage(parent.Handle, WM_SETREDRAW, true, 0); parent.Refresh(); } #endregion public TreeViewCustom() { InitializeComponent(); } protected override void WndProc(ref Message m) { if (m.Msg == 0x0014) return; base.WndProc(ref m); } /// /// 注册设置事件 /// /// public void SetClickEvent(ButtonClickEventHandler clickEvent) { this.clickEvent = clickEvent; } /// /// 检查是否包含父节点 /// /// private List getParentNodes(string parent) { string parentKey = parent.Length == ParentKeyLength ? parent : parent.Substring(0, parent.Length - ParentKeyLength); List treeNodeList = new List(); if (dicTreeNodes == null) dicTreeNodes = new Dictionary>(); if (dicTreeNodes.ContainsKey(parentKey)) { treeNodeList = dicTreeNodes[parentKey]; } else { dicTreeNodes.Add(parentKey, treeNodeList); } return treeNodeList; } /// /// 加载菜单 /// /// /// public void SetDataSource(DataTable dtTable) { int index = 1; this.dataSource = dtTable; if (dataSource == null || dataSource.Rows.Count == 0) return; // 获取根节点 DataRow[] rootRows = dataSource.Rows.Cast().Where(x => (x[ParentField] + "").Length == ParentKeyLength || (x[ParentField] + "").Length == ParentKeyLength * 2).ToArray(); foreach (DataRow item in dataSource.Rows) { int length = (item[ParentField] + "").Length; TreeNodeCustom treeNode = new TreeNodeCustom(); treeNode.Dock = DockStyle.Top; treeNode.Tag = item[ParentField] + ""; treeNode.TabIndex = index; if (length == ParentKeyLength) { treeNode.btnTreeNode.BackgroundImage = Resources.node_default; treeNode.btnTreeNode.Font = new Font("微软雅黑", 12); } else if (length / ParentKeyLength == 2) { treeNode.btnTreeNode.BackgroundImage = Resources.node2_default; treeNode.btnTreeNode.Padding = new Padding(20, 1, 3, 3); treeNode.btnTreeNode.Font = new Font("微软雅黑", 11); } else { treeNode.btnTreeNode.BackgroundImage = Resources.node3_default; treeNode.btnTreeNode.Padding = new Padding(30, 1, 3, 3); treeNode.btnTreeNode.Font = new Font("微软雅黑", 10); } treeNode.btnTreeNode.Name = index + ""; treeNode.btnTreeNode.Text = item[TextField] + ""; treeNode.btnTreeNode.Tag = item; treeNode.btnTreeNode.Click += new EventHandler(btnTreeNode_Click); treeNode.btnTreeNode.MouseMove += new MouseEventHandler(btnTreeNode_MouseMove); treeNode.btnTreeNode.MouseLeave += new EventHandler(btnTreeNode_MouseLeave); plTreeView.Controls.Add(treeNode); dicButtons.Add(index + "", treeNode.btnTreeNode); List parentNodes = getParentNodes(item[ParentField] + ""); parentNodes.Add(treeNode); // 隐藏需要放在添加后,否则出现顺序错乱 treeNode.Visible = length == ParentKeyLength; index++; } } /// /// 树节点点击 /// /// /// private void btnTreeNode_Click(object sender, EventArgs e) { try { SuspendDrawing(plTreeView); TreeNodeCustom treeNode = (sender as Button).Parent as TreeNodeCustom; if (treeNode != null) { string nodeValue = treeNode.Tag + ""; if (lastTreeNode == null) { lastTreeNode = nodeValue; } if (nodeValue.Length == ParentKeyLength) { treeNode.btnTreeNode.BackgroundImage = dicTreeNodes[nodeValue][0].Visible ? Resources.node_default : Resources.node_select; } if (nodeValue.Length == ParentKeyLength * 2) { treeNode.btnTreeNode.BackgroundImage = dicTreeNodes[nodeValue][0].Visible ? Resources.node2_default : Resources.node2_select; } // 末节点 if (nodeValue.Length == ParentKeyLength * 3) { treeNode.btnTreeNode.BackgroundImage = Resources.node3_select; if (!string.IsNullOrEmpty(lastMenuId) && lastMenuId != treeNode.btnTreeNode.Name) { dicButtons[lastMenuId].BackgroundImage = Resources.node3_default; } lastMenuId = treeNode.btnTreeNode.Name; } List treeNodes = new List(); // 展开当前点击节点 if (dicTreeNodes.ContainsKey(nodeValue)) { treeNodes = dicTreeNodes[nodeValue]; foreach (TreeNodeCustom node in treeNodes) { string menuKey = node.Tag + ""; if (menuKey.Length == ParentKeyLength) continue; node.Visible = !node.Visible; Application.DoEvents();// 处理当前消息队列中的所有windows消息 } } // 点击根节点隐藏所有子节点 if (nodeValue.Length == ParentKeyLength && !dicTreeNodes[nodeValue][0].Visible) { treeNodes = getChildNodes(nodeValue); foreach (TreeNodeCustom node in treeNodes) { node.Visible = false; //Application.DoEvents();// 处理当前消息队列中的所有windows消息 } } // 点击末节点 if (nodeValue.Length == ParentKeyLength * 3) { if (clickEvent != null) { this.clickEvent(treeNode.btnTreeNode); } } lastTreeNode = nodeValue; } } catch (Exception) { } ResumeDrawing(plTreeView); } /// /// 鼠标移动 /// /// /// private void btnTreeNode_MouseMove(object sender, MouseEventArgs e) { try { Button button = sender as Button; if (button != null) { this.Cursor = Cursors.Hand; TreeNodeCustom treeNode = button.Parent as TreeNodeCustom; string treeNodeTag = treeNode.Tag + ""; if (treeNodeTag.Length == ParentKeyLength) { // 根节点 //bool isOpen = false; //List nodes = getChildNodes(treeNodeTag); //foreach (TreeNodeCustom item in nodes) //{ // if (item.Visible) // { // isOpen = true; // break; // } //} //if (!isOpen) //{ // button.BackgroundImage = Resources.node_move; //} } else if (treeNodeTag.Length == ParentKeyLength * 2) { // 第一级节点 if (dicTreeNodes.ContainsKey(treeNodeTag) && dicTreeNodes[treeNodeTag].Count > 0) { button.BackgroundImage = dicTreeNodes[treeNodeTag][0].Visible ? Resources.node2_select : Resources.node2_move; } else { button.BackgroundImage = Resources.node2_move; } } else { // 末节点 if (button.Name != lastMenuId) { button.BackgroundImage = Resources.node3_move; } } } } catch (Exception ex) { } } /// /// 鼠标离开 /// /// /// private void btnTreeNode_MouseLeave(object sender, EventArgs e) { try { Button button = sender as Button; if (button != null) { this.Cursor = Cursors.Hand; TreeNodeCustom treeNode = button.Parent as TreeNodeCustom; string treeNodeTag = treeNode.Tag + ""; if (treeNodeTag.Length == ParentKeyLength) { // 根节点 //bool isOpen = false; //List nodes = getChildNodes(treeNodeTag); //foreach (TreeNodeCustom item in nodes) //{ // if (item.Visible) // { // isOpen = true; // break; // } //} //if (!isOpen) //{ // button.BackgroundImage = Resources.node_move; //} } else if (treeNodeTag.Length == ParentKeyLength * 2) { // 第一级节点 if (dicTreeNodes.ContainsKey(treeNodeTag) && dicTreeNodes[treeNodeTag].Count > 0) { button.BackgroundImage = dicTreeNodes[treeNodeTag][0].Visible ? Resources.node2_select : Resources.node2_default; } else { button.BackgroundImage = Resources.node2_default; } } else { // 末节点 if (button.Name != lastMenuId) { button.BackgroundImage = Resources.node3_default; } } } } catch (Exception ex) { } } /// /// 获取子节点 /// /// private List getChildNodes(string nodeValue) { List treeNodes = new List(); // 获取第3个节点之后的节点 DataRow[] rowChilds = dataSource.Rows.Cast().Where(x => (x[ParentField] + "").Length == nodeValue.Length * 2 && (x[ParentField] + "").Substring(0, nodeValue.Length) == nodeValue).ToArray(); foreach (DataRow item in rowChilds) { if (dicTreeNodes.ContainsKey(item[ParentField] + "")) { List nodeChilds = dicTreeNodes[item[ParentField] + ""]; foreach (TreeNodeCustom node in nodeChilds) { treeNodes.Add(node); } } } return treeNodes; } } }