/*********************** * 说明:主界面左菜单树 * 创建人:龚宇超 * 创建日期:2018-04-25 * 修改人: * 修改日期: * 修改备注: * 版本:1.0.0.0 ***********************/ 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 System.Runtime.InteropServices; namespace Lskj.Main.Control { public partial class TreeViewCustom : UserControl { #region 公有属性 /// /// 父节点字段 /// public string ParentField; /// /// 显示节点文本字段 /// public string TextField; /// /// 父节点关联子节点位数 /// public int ParentKeyLength; /// /// 左侧菜单点击回调 /// /// The after. public delegate void ButtonClickEventHandler(Button after); /// /// 左侧菜单事件注册 /// public ButtonClickEventHandler OnButtonClickEvent; #endregion #region 私有属性 /// /// 上次显示节点 /// private string _lastTreeNode; /// /// 上次显示按钮ID /// private string _lastMenuId; /// 数据源 /// private DataTable _dataSource; /// /// 缓存菜单,按照节点缓存 /// 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; /// /// 说明:停止绘制 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// public static void SuspendDrawing(System.Windows.Forms.Control parent) { SendMessage(parent.Handle, WM_SETREDRAW, false, 0); } /// /// 说明:开始绘制 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// public static void ResumeDrawing(System.Windows.Forms.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); } /// /// 说明:检查是否包含父节点 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// 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; } /// /// 说明:加载菜单 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// 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 = Lskj.Main.Properties.Resources.node_default; treeNode.btnTreeNode.Font = new Font("微软雅黑", 12); } else if (length / ParentKeyLength == 2) { treeNode.btnTreeNode.BackgroundImage = Lskj.Main.Properties.Resources.node2_default; treeNode.btnTreeNode.Padding = new Padding(20, 1, 3, 3); treeNode.btnTreeNode.Font = new Font("微软雅黑", 11); } else { treeNode.btnTreeNode.BackgroundImage = Lskj.Main.Properties.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++; } } /// /// 说明:树点击 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// 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 ? Lskj.Main.Properties.Resources.node_default : Lskj.Main.Properties.Resources.node_select; } if (nodeValue.Length == ParentKeyLength * 2) { treeNode.btnTreeNode.BackgroundImage = _dicTreeNodes[nodeValue][0].Visible ? Lskj.Main.Properties.Resources.node2_default : Lskj.Main.Properties.Resources.node2_select; } // 末节点 if (nodeValue.Length == ParentKeyLength * 3) { treeNode.btnTreeNode.BackgroundImage = Lskj.Main.Properties.Resources.node3_select; if (!string.IsNullOrEmpty(_lastMenuId) && _lastMenuId != treeNode.btnTreeNode.Name) { _dicButtons[_lastMenuId].BackgroundImage = Lskj.Main.Properties.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 (OnButtonClickEvent != null) { this.OnButtonClickEvent(treeNode.btnTreeNode); } } _lastTreeNode = nodeValue; } } catch (Exception) { } ResumeDrawing(plTreeView); } /// /// 说明:鼠标移动 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// 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) { } else if (treeNodeTag.Length == ParentKeyLength * 2) { // 第一级节点 if (_dicTreeNodes.ContainsKey(treeNodeTag) && _dicTreeNodes[treeNodeTag].Count > 0) { button.BackgroundImage = _dicTreeNodes[treeNodeTag][0].Visible ? Lskj.Main.Properties.Resources.node2_select : Lskj.Main.Properties.Resources.node2_move; } else { button.BackgroundImage = Lskj.Main.Properties.Resources.node2_move; } } else { // 末节点 if (button.Name != _lastMenuId) { button.BackgroundImage = Lskj.Main.Properties.Resources.node3_move; } } } } catch (Exception ex) { } } /// /// 说明:鼠标离开 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// 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) { } else if (treeNodeTag.Length == ParentKeyLength * 2) { // 第一级节点 if (_dicTreeNodes.ContainsKey(treeNodeTag) && _dicTreeNodes[treeNodeTag].Count > 0) { button.BackgroundImage = _dicTreeNodes[treeNodeTag][0].Visible ? Lskj.Main.Properties.Resources.node2_select : Lskj.Main.Properties.Resources.node2_default; } else { button.BackgroundImage = Lskj.Main.Properties.Resources.node2_default; } } else { // 末节点 if (button.Name != _lastMenuId) { button.BackgroundImage = Lskj.Main.Properties.Resources.node3_default; } } } } catch (Exception ex) { } } /// /// 说明:获取子节点 /// 创建人 龚宇超 /// 创建日期:2018-04-24 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// 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; } } }