(七十九)c#Winform自定义控件-导航菜单

不打扰是莪最后的温柔 提交于 2019-11-30 20:48:06

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

来都来了,点个【推荐】再走吧,谢谢

NuGet

Install-Package HZH_Controls

目录

https://www.cnblogs.com/bfyx/p/11364884.html

用处及效果

准备工作

主要用的就是停靠窗体了,(十九)c#Winform自定义控件-停靠窗体,不了解的可以先去看一下

思路:

通过实体对象设置的对齐方式来实现左右对齐,

当鼠标进入一项的时候,判断是否弹出下拉列表,或关闭其他列表

开始

添加一个类用来设置节点信息

 

  1   public class NavigationMenuItem    2     {    3         /// <summary>    4         /// The icon    5         /// </summary>    6         private Image icon;    7         /// <summary>    8         /// Gets or sets the icon.    9         /// </summary>   10         /// <value>The icon.</value>   11         [Description("图标,仅顶级节点有效")]   12         public Image Icon   13         {   14             get { return icon; }   15             set { icon = value; }   16         }   17    18         /// <summary>   19         /// The text   20         /// </summary>   21         private string text;   22         /// <summary>   23         /// Gets or sets the text.   24         /// </summary>   25         /// <value>The text.</value>   26    27         [Description("文本")]   28         public string Text   29         {   30             get { return text; }   31             set { text = value; }   32         }   33    34         /// <summary>   35         /// The show tip   36         /// </summary>   37         private bool showTip;   38         /// <summary>   39         /// Gets or sets a value indicating whether [show tip].当TipText为空时只显示一个小圆点,否则显示TipText文字   40         /// </summary>   41         /// <value><c>true</c> if [show tip]; otherwise, <c>false</c>.</value>   42         [Description("是否显示角标,仅顶级节点有效")]   43         public bool ShowTip   44         {   45             get { return showTip; }   46             set { showTip = value; }   47         }   48    49         /// <summary>   50         /// The tip text   51         /// </summary>   52         private string tipText;   53         /// <summary>   54         /// Gets or sets the tip text   55         /// </summary>   56         /// <value>The tip text.</value>   57         [Description("角标文字,仅顶级节点有效")]   58         public string TipText   59         {   60             get { return tipText; }   61             set { tipText = value; }   62         }   63         /// <summary>   64         /// The items   65         /// </summary>   66         private NavigationMenuItem[] items;   67         /// <summary>   68         /// Gets or sets the items.   69         /// </summary>   70         /// <value>The items.</value>   71         [Description("子项列表")]   72         public NavigationMenuItem[] Items   73         {   74             get { return items; }   75             set   76             {   77                 items = value;   78                 if (value != null)   79                 {   80                     foreach (var item in value)   81                     {   82                         item.ParentItem = this;   83                     }   84                 }   85             }   86         }   87    88         /// <summary>   89         /// The anchor right   90         /// </summary>   91         private bool anchorRight;   92    93         /// <summary>   94         /// Gets or sets a value indicating whether [anchor right].   95         /// </summary>   96         /// <value><c>true</c> if [anchor right]; otherwise, <c>false</c>.</value>   97         [Description("是否靠右对齐")]   98         public bool AnchorRight   99         {  100             get { return anchorRight; }  101             set { anchorRight = value; }  102         }  103   104         /// <summary>  105         /// The item width  106         /// </summary>  107         private int itemWidth = 100;  108   109         /// <summary>  110         /// Gets or sets the width of the item.  111         /// </summary>  112         /// <value>The width of the item.</value>  113         [Description("宽度")]  114         public int ItemWidth  115         {  116             get { return itemWidth; }  117             set { itemWidth = value; }  118         }  119   120         /// <summary>  121         /// Gets or sets the data source.  122         /// </summary>  123         /// <value>The data source.</value>  124         [Description("数据源")]  125         public object DataSource { get; set; }  126         /// <summary>  127         /// Gets or sets a value indicating whether this instance has split lint at top.  128         /// </summary>  129         /// <value><c>true</c> if this instance has split lint at top; otherwise, <c>false</c>.</value>  130         [Description("是否在此项顶部显示一个分割线")]  131         public bool HasSplitLintAtTop { get; set; }  132   133         /// <summary>  134         /// Gets the parent item.  135         /// </summary>  136         /// <value>The parent item.</value>  137         [Description("父节点")]  138         public NavigationMenuItem ParentItem { get; private set; }  139     }

添加一个自定义控件UCNavigationMenu

添加一些属性

  1 /// <summary>    2         /// Occurs when [click itemed].    3         /// </summary>    4         [Description("点击节点事件"), Category("自定义")]    5     6         public event EventHandler ClickItemed;    7         /// <summary>    8         /// The select item    9         /// </summary>   10         private NavigationMenuItem selectItem = null;   11    12         /// <summary>   13         /// Gets the select item.   14         /// </summary>   15         /// <value>The select item.</value>   16         [Description("选中的节点"), Category("自定义")]   17         public NavigationMenuItem SelectItem   18         {   19             get { return selectItem; }   20             private set { selectItem = value; }   21         }   22    23    24         /// <summary>   25         /// The items   26         /// </summary>   27         NavigationMenuItem[] items;   28    29         /// <summary>   30         /// Gets or sets the items.   31         /// </summary>   32         /// <value>The items.</value>   33         [Description("节点列表"), Category("自定义")]   34         public NavigationMenuItem[] Items   35         {   36             get { return items; }   37             set   38             {   39                 items = value;   40                 ReloadMenu();   41             }   42         }   43    44         /// <summary>   45         /// The tip color   46         /// </summary>   47         private Color tipColor = Color.FromArgb(255, 87, 34);   48    49         /// <summary>   50         /// Gets or sets the color of the tip.   51         /// </summary>   52         /// <value>The color of the tip.</value>   53         [Description("角标颜色"), Category("自定义")]   54         public Color TipColor   55         {   56             get { return tipColor; }   57             set { tipColor = value; }   58         }   59    60         /// <summary>   61         /// 获取或设置控件的前景色。   62         /// </summary>   63         /// <value>The color of the fore.</value>   64         /// <PermissionSet>   65         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />   66         /// </PermissionSet>   67         public override System.Drawing.Color ForeColor   68         {   69             get   70             {   71                 return base.ForeColor;   72             }   73             set   74             {   75                 base.ForeColor = value;   76                 foreach (Control c in this.Controls)   77                 {   78                     c.ForeColor = value;   79                 }   80             }   81         }   82         /// <summary>   83         /// 获取或设置控件显示的文字的字体。   84         /// </summary>   85         /// <value>The font.</value>   86         /// <PermissionSet>   87         ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />   88         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />   89         ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />   90         ///   <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />   91         /// </PermissionSet>   92         public override Font Font   93         {   94             get   95             {   96                 return base.Font;   97             }   98             set   99             {  100                 base.Font = value;  101                 foreach (Control c in this.Controls)  102                 {  103                     c.Font = value;  104                 }  105             }  106         }  107   108         /// <summary>  109         /// The m LST anchors  110         /// </summary>  111         Dictionary<NavigationMenuItem, FrmAnchor> m_lstAnchors = new Dictionary<NavigationMenuItem, FrmAnchor>();

重载菜单

 1   private void ReloadMenu()   2         {   3             try   4             {   5                 ControlHelper.FreezeControl(this, true);   6                 this.Controls.Clear();   7                 if (items != null && items.Length > 0)   8                 {   9                     foreach (var item in items)  10                     {  11                         var menu = (NavigationMenuItem)item;  12                         Label lbl = new Label();  13                         lbl.AutoSize = false;  14                         lbl.TextAlign = ContentAlignment.MiddleCenter;  15                         lbl.Width = menu.ItemWidth;  16                         lbl.Text = menu.Text;  17   18                         lbl.Font = Font;  19                         lbl.ForeColor = ForeColor;  20   21                         lbl.Paint += lbl_Paint;  22                         lbl.MouseEnter += lbl_MouseEnter;  23                         lbl.Tag = menu;  24                         lbl.Click += lbl_Click;  25                         if (menu.AnchorRight)  26                         {  27                             lbl.Dock = DockStyle.Right;  28                         }  29                         else  30                         {  31                             lbl.Dock = DockStyle.Left;  32                         }  33                         this.Controls.Add(lbl);  34   35                         lbl.BringToFront();  36                     }  37   38   39                 }  40             }  41             finally  42             {  43                 ControlHelper.FreezeControl(this, false);  44             }  45         }

显示下级菜单

 1 private void ShowMoreMenu(Label lbl)   2         {   3             var menu = (NavigationMenuItem)lbl.Tag;   4             if (CheckShow(menu))   5             {   6                 if (menu.Items != null && menu.Items.Length > 0)   7                 {   8                     Panel panel = new Panel();   9                     panel.BackColor = Color.White;  10                     panel.Paint += panel_Paint;  11                     panel.Padding = new System.Windows.Forms.Padding(1);  12                     Size size = GetItemsSize(menu.Items);  13                     var height = size.Height * menu.Items.Length + 2;  14                     height += menu.Items.Count(p => p.HasSplitLintAtTop);//分割线  15                     if (size.Width < lbl.Width)  16                         size.Width = lbl.Width;  17                     panel.Size = new Size(size.Width, height);  18   19                     foreach (var item in menu.Items)  20                     {  21                         if (item.HasSplitLintAtTop)  22                         {  23                             UCSplitLine_H line = new UCSplitLine_H();  24                             line.Dock = DockStyle.Top;  25                             panel.Controls.Add(line);  26                             line.BringToFront();  27                         }  28                         Label _lbl = new Label();  29                         _lbl.Font = Font;  30                         _lbl.ForeColor = this.BackColor;  31                         _lbl.AutoSize = false;  32                         _lbl.TextAlign = ContentAlignment.MiddleCenter;  33                         _lbl.Height = size.Height;  34                         _lbl.Text = item.Text;  35                         _lbl.Dock = DockStyle.Top;  36                         _lbl.BringToFront();  37                         _lbl.Paint += lbl_Paint;  38                         _lbl.MouseEnter += lbl_MouseEnter;  39                         _lbl.Tag = item;  40                         _lbl.Click += lbl_Click;  41                         _lbl.Size = new System.Drawing.Size(size.Width, size.Height);  42                         panel.Controls.Add(_lbl);  43                         _lbl.BringToFront();  44                     }  45                     Point point = Point.Empty;  46   47                     if (menu.ParentItem != null)  48                     {  49                         Point p = lbl.Parent.PointToScreen(lbl.Location);  50                         if (p.X + lbl.Width + panel.Width > Screen.PrimaryScreen.Bounds.Width)  51                         {  52                             point = new Point(-1 * panel.Width - 2, -1 * lbl.Height);  53                         }  54                         else  55                         {  56                             point = new Point(panel.Width + 2, -1 * lbl.Height);  57                         }  58                     }  59                     m_lstAnchors[menu] = new FrmAnchor(lbl, panel, point);  60                     m_lstAnchors[menu].FormClosing += UCNavigationMenu_FormClosing;  61                     m_lstAnchors[menu].Show();  62                     m_lstAnchors[menu].Size = new Size(size.Width, height);  63                 }  64             }  65   66         }

辅助函数

 1   /// <summary>   2         /// Checks the show.   3         /// </summary>   4         /// <param name="menu">The menu.</param>   5         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>   6         private bool CheckShow(NavigationMenuItem menu)   7         {   8             //检查已经打开的节点   9             if (m_lstAnchors.ContainsKey(menu))  10             {  11                 CloseList(menu);  12                 return false;  13             }  14             if (HasInCacheChild(menu))  15             {  16                 if (m_lstAnchors.ContainsKey(menu.ParentItem))  17                 {  18                     CloseList(menu.ParentItem);  19                     return true;  20                 }  21                 return false;  22             }  23             else  24             {  25                 for (int i = 0; i < 1; )  26                 {  27                     try  28                     {  29                         foreach (var item in m_lstAnchors)  30                         {  31                             if (m_lstAnchors[item.Key] != null && !m_lstAnchors[item.Key].IsDisposed)  32                             {  33                                 m_lstAnchors[item.Key].Close();  34                             }  35                         }  36                     }  37                     catch  38                     {  39                         continue;  40                     }  41                     i++;  42                 }  43                 m_lstAnchors.Clear();  44                 return true;  45             }  46         }  47   48         /// <summary>  49         /// Determines whether [has in cache child] [the specified menu].  50         /// </summary>  51         /// <param name="menu">The menu.</param>  52         /// <returns><c>true</c> if [has in cache child] [the specified menu]; otherwise, <c>false</c>.</returns>  53         private bool HasInCacheChild(NavigationMenuItem menu)  54         {  55             foreach (var item in m_lstAnchors)  56             {  57                 if (item.Key == menu)  58                 {  59                     return true;  60                 }  61                 else  62                 {  63                     if (item.Key.Items != null)  64                     {  65                         if (item.Key.Items.Contains(menu))  66                             return true;  67                     }  68                 }  69             }  70             return false;  71         }  72   73         /// <summary>  74         /// Closes the list.  75         /// </summary>  76         /// <param name="menu">The menu.</param>  77         private void CloseList(NavigationMenuItem menu)  78         {  79             if (menu.Items != null)  80             {  81                 foreach (var item in menu.Items)  82                 {  83                     CloseList(item);  84                     if (m_lstAnchors.ContainsKey(item))  85                     {  86                         if (m_lstAnchors[item] != null && !m_lstAnchors[item].IsDisposed)  87                         {  88                             m_lstAnchors[item].Close();  89                             m_lstAnchors[item] = null;  90                             m_lstAnchors.Remove(item);  91                         }  92                     }  93                 }  94             }  95         }

一些事件

  1 /// <summary>    2         /// Handles the Click event of the lbl control.    3         /// </summary>    4         /// <param name="sender">The source of the event.</param>    5         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>    6         void lbl_Click(object sender, EventArgs e)    7         {    8             Label lbl = sender as Label;    9             if (lbl.Tag != null)   10             {   11                 var menu = (NavigationMenuItem)lbl.Tag;   12                 if (menu.Items == null || menu.Items.Length <= 0)   13                 {   14                     selectItem = menu;   15    16                     while (m_lstAnchors.Count > 0)   17                     {   18                         try   19                         {   20                             foreach (var item in m_lstAnchors)   21                             {   22                                 item.Value.Close();   23                                 m_lstAnchors.Remove(item.Key);   24                             }   25                         }   26                         catch { }   27                     }   28    29                     if (ClickItemed != null)   30                     {   31                         ClickItemed(this, e);   32                     }   33                 }   34                 else   35                 {   36                     CloseList(menu);   37                     if (m_lstAnchors.ContainsKey(menu))   38                     {   39                         if (m_lstAnchors[menu] != null && !m_lstAnchors[menu].IsDisposed)   40                         {   41                             m_lstAnchors[menu].Close();   42                         }   43                         m_lstAnchors.Remove(menu);   44                     }   45                     ShowMoreMenu(lbl);   46                 }   47             }   48         }   49    50         /// <summary>   51         /// Handles the MouseEnter event of the lbl control.   52         /// </summary>   53         /// <param name="sender">The source of the event.</param>   54         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>   55         void lbl_MouseEnter(object sender, EventArgs e)   56         {   57             Label lbl = sender as Label;   58             ShowMoreMenu(lbl);   59         }   60 /// <summary>   61         /// Handles the FormClosing event of the UCNavigationMenu control.   62         /// </summary>   63         /// <param name="sender">The source of the event.</param>   64         /// <param name="e">The <see cref="FormClosingEventArgs"/> instance containing the event data.</param>   65         void UCNavigationMenu_FormClosing(object sender, FormClosingEventArgs e)   66         {   67             FrmAnchor frm = sender as FrmAnchor;   68             if (m_lstAnchors.ContainsValue(frm))   69             {   70                 foreach (var item in m_lstAnchors)   71                 {   72                     if (item.Value == frm)   73                     {   74                         m_lstAnchors.Remove(item.Key);   75                         return;   76                     }   77                 }   78             }   79         }   80    81         /// <summary>   82         /// Handles the Paint event of the panel control.   83         /// </summary>   84         /// <param name="sender">The source of the event.</param>   85         /// <param name="e">The <see cref="PaintEventArgs"/> instance containing the event data.</param>   86         void panel_Paint(object sender, PaintEventArgs e)   87         {   88             e.Graphics.SetGDIHigh();   89             Rectangle rect = new Rectangle(0, 0, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);   90             var path = rect.CreateRoundedRectanglePath(2);   91             e.Graphics.DrawPath(new Pen(new SolidBrush(LineColors.Light)), path);   92         }   93    94    95    96         /// <summary>   97         /// Gets the size of the items.   98         /// </summary>   99         /// <param name="items">The items.</param>  100         /// <returns>Size.</returns>  101         private Size GetItemsSize(NavigationMenuItem[] items)  102         {  103             Size size = Size.Empty;  104             if (items != null && items.Length > 0)  105             {  106                 using (var g = this.CreateGraphics())  107                 {  108                     foreach (NavigationMenuItem item in items)  109                     {  110                         var s = g.MeasureString(item.Text, Font);  111                         if (s.Width + 25 > size.Width)  112                         {  113                             size.Width = (int)s.Width + 25;  114                         }  115                         if (s.Height + 10 > size.Height)  116                         {  117                             size.Height = (int)s.Height + 10;  118                         }  119                     }  120                 }  121             }  122             return size;  123         }  124   125   126         /// <summary>  127         /// Handles the Paint event of the lbl control.  128         /// </summary>  129         /// <param name="sender">The source of the event.</param>  130         /// <param name="e">The <see cref="PaintEventArgs"/> instance containing the event data.</param>  131         void lbl_Paint(object sender, PaintEventArgs e)  132         {  133             Label lbl = sender as Label;  134             if (lbl.Tag != null)  135             {  136                 var menu = (NavigationMenuItem)lbl.Tag;  137                 e.Graphics.SetGDIHigh();  138                 if (menu.ParentItem == null)//顶级节点支持图标和角标  139                 {  140                     if (menu.ShowTip)  141                     {  142                         if (!string.IsNullOrEmpty(menu.TipText))  143                         {  144                             var rect = new Rectangle(lbl.Width - 25, lbl.Height / 2 - 10, 20, 20);  145                             var path = rect.CreateRoundedRectanglePath(5);  146                             e.Graphics.FillPath(new SolidBrush(tipColor), path);  147                             e.Graphics.DrawString(menu.TipText, new Font("微软雅黑", 8f), new SolidBrush(Color.White), rect, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });  148                         }  149                         else  150                         {  151                             e.Graphics.FillEllipse(new SolidBrush(tipColor), new Rectangle(lbl.Width - 20, lbl.Height / 2 - 10, 10, 10));  152                         }  153                     }  154                     if (menu.Icon != null)  155                     {  156                         e.Graphics.DrawImage(menu.Icon, new Rectangle(1, (lbl.Height - 25) / 2, 25, 25), 0, 0, menu.Icon.Width, menu.Icon.Height, GraphicsUnit.Pixel);  157                     }  158                 }  159                 if (menu.ParentItem != null && menu.Items != null && menu.Items.Length > 0)  160                 {  161                     ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(this.BackColor), new Point(lbl.Width - 11, (lbl.Height - 5) / 2), 5, GraphDirection.Rightward);  162                 }  163             }  164         }

完整代码

  1 // ***********************************************************************    2 // Assembly         : HZH_Controls    3 // Created          : 2019-10-08    4 //    5 // ***********************************************************************    6 // <copyright file="UCNavigationMenu.cs">    7 //     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com    8 // </copyright>    9 //   10 // Blog: https://www.cnblogs.com/bfyx   11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl   12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git   13 //   14 // If you use this code, please keep this note.   15 // ***********************************************************************   16 using System;   17 using System.Collections.Generic;   18 using System.ComponentModel;   19 using System.Drawing;   20 using System.Data;   21 using System.Linq;   22 using System.Text;   23 using System.Windows.Forms;   24 using HZH_Controls.Forms;   25    26 namespace HZH_Controls.Controls   27 {   28     /// <summary>   29     /// Class UCNavigationMenu.   30     /// Implements the <see cref="System.Windows.Forms.UserControl" />   31     /// </summary>   32     /// <seealso cref="System.Windows.Forms.UserControl" />   33     [DefaultEvent("ClickItemed")]   34     public partial class UCNavigationMenu : UserControl   35     {   36         /// <summary>   37         /// Occurs when [click itemed].   38         /// </summary>   39         [Description("点击节点事件"), Category("自定义")]   40    41         public event EventHandler ClickItemed;   42         /// <summary>   43         /// The select item   44         /// </summary>   45         private NavigationMenuItem selectItem = null;   46    47         /// <summary>   48         /// Gets the select item.   49         /// </summary>   50         /// <value>The select item.</value>   51         [Description("选中的节点"), Category("自定义")]   52         public NavigationMenuItem SelectItem   53         {   54             get { return selectItem; }   55             private set { selectItem = value; }   56         }   57    58    59         /// <summary>   60         /// The items   61         /// </summary>   62         NavigationMenuItem[] items;   63    64         /// <summary>   65         /// Gets or sets the items.   66         /// </summary>   67         /// <value>The items.</value>   68         [Description("节点列表"), Category("自定义")]   69         public NavigationMenuItem[] Items   70         {   71             get { return items; }   72             set   73             {   74                 items = value;   75                 ReloadMenu();   76             }   77         }   78    79         /// <summary>   80         /// The tip color   81         /// </summary>   82         private Color tipColor = Color.FromArgb(255, 87, 34);   83    84         /// <summary>   85         /// Gets or sets the color of the tip.   86         /// </summary>   87         /// <value>The color of the tip.</value>   88         [Description("角标颜色"), Category("自定义")]   89         public Color TipColor   90         {   91             get { return tipColor; }   92             set { tipColor = value; }   93         }   94    95         /// <summary>   96         /// 获取或设置控件的前景色。   97         /// </summary>   98         /// <value>The color of the fore.</value>   99         /// <PermissionSet>  100         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />  101         /// </PermissionSet>  102         public override System.Drawing.Color ForeColor  103         {  104             get  105             {  106                 return base.ForeColor;  107             }  108             set  109             {  110                 base.ForeColor = value;  111                 foreach (Control c in this.Controls)  112                 {  113                     c.ForeColor = value;  114                 }  115             }  116         }  117         /// <summary>  118         /// 获取或设置控件显示的文字的字体。  119         /// </summary>  120         /// <value>The font.</value>  121         /// <PermissionSet>  122         ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />  123         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />  124         ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />  125         ///   <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />  126         /// </PermissionSet>  127         public override Font Font  128         {  129             get  130             {  131                 return base.Font;  132             }  133             set  134             {  135                 base.Font = value;  136                 foreach (Control c in this.Controls)  137                 {  138                     c.Font = value;  139                 }  140             }  141         }  142   143         /// <summary>  144         /// The m LST anchors  145         /// </summary>  146         Dictionary<NavigationMenuItem, FrmAnchor> m_lstAnchors = new Dictionary<NavigationMenuItem, FrmAnchor>();  147   148         /// <summary>  149         /// Initializes a new instance of the <see cref="UCNavigationMenu"/> class.  150         /// </summary>  151         public UCNavigationMenu()  152         {  153             InitializeComponent();  154             items = new NavigationMenuItem[0];  155             if (ControlHelper.IsDesignMode())  156             {  157                 items = new NavigationMenuItem[4];  158                 for (int i = 0; i < 4; i++)  159                 {  160                     items[i] = new NavigationMenuItem()  161                     {  162                         Text = "菜单" + (i + 1),  163                         AnchorRight = i >= 2  164                     };  165                 }  166             }  167         }  168   169         /// <summary>  170         /// Reloads the menu.  171         /// </summary>  172         private void ReloadMenu()  173         {  174             try  175             {  176                 ControlHelper.FreezeControl(this, true);  177                 this.Controls.Clear();  178                 if (items != null && items.Length > 0)  179                 {  180                     foreach (var item in items)  181                     {  182                         var menu = (NavigationMenuItem)item;  183                         Label lbl = new Label();  184                         lbl.AutoSize = false;  185                         lbl.TextAlign = ContentAlignment.MiddleCenter;  186                         lbl.Width = menu.ItemWidth;  187                         lbl.Text = menu.Text;  188   189                         lbl.Font = Font;  190                         lbl.ForeColor = ForeColor;  191   192                         lbl.Paint += lbl_Paint;  193                         lbl.MouseEnter += lbl_MouseEnter;  194                         lbl.Tag = menu;  195                         lbl.Click += lbl_Click;  196                         if (menu.AnchorRight)  197                         {  198                             lbl.Dock = DockStyle.Right;  199                         }  200                         else  201                         {  202                             lbl.Dock = DockStyle.Left;  203                         }  204                         this.Controls.Add(lbl);  205   206                         lbl.BringToFront();  207                     }  208   209   210                 }  211             }  212             finally  213             {  214                 ControlHelper.FreezeControl(this, false);  215             }  216         }  217   218   219   220         /// <summary>  221         /// Handles the Click event of the lbl control.  222         /// </summary>  223         /// <param name="sender">The source of the event.</param>  224         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>  225         void lbl_Click(object sender, EventArgs e)  226         {  227             Label lbl = sender as Label;  228             if (lbl.Tag != null)  229             {  230                 var menu = (NavigationMenuItem)lbl.Tag;  231                 if (menu.Items == null || menu.Items.Length <= 0)  232                 {  233                     selectItem = menu;  234   235                     while (m_lstAnchors.Count > 0)  236                     {  237                         try  238                         {  239                             foreach (var item in m_lstAnchors)  240                             {  241                                 item.Value.Close();  242                                 m_lstAnchors.Remove(item.Key);  243                             }  244                         }  245                         catch { }  246                     }  247   248                     if (ClickItemed != null)  249                     {  250                         ClickItemed(this, e);  251                     }  252                 }  253                 else  254                 {  255                     CloseList(menu);  256                     if (m_lstAnchors.ContainsKey(menu))  257                     {  258                         if (m_lstAnchors[menu] != null && !m_lstAnchors[menu].IsDisposed)  259                         {  260                             m_lstAnchors[menu].Close();  261                         }  262                         m_lstAnchors.Remove(menu);  263                     }  264                     ShowMoreMenu(lbl);  265                 }  266             }  267         }  268   269         /// <summary>  270         /// Handles the MouseEnter event of the lbl control.  271         /// </summary>  272         /// <param name="sender">The source of the event.</param>  273         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>  274         void lbl_MouseEnter(object sender, EventArgs e)  275         {  276             Label lbl = sender as Label;  277             ShowMoreMenu(lbl);  278         }  279   280         /// <summary>  281         /// Checks the show.  282         /// </summary>  283         /// <param name="menu">The menu.</param>  284         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>  285         private bool CheckShow(NavigationMenuItem menu)  286         {  287             //检查已经打开的节点  288             if (m_lstAnchors.ContainsKey(menu))  289             {  290                 CloseList(menu);  291                 return false;  292             }  293             if (HasInCacheChild(menu))  294             {  295                 if (m_lstAnchors.ContainsKey(menu.ParentItem))  296                 {  297                     CloseList(menu.ParentItem);  298                     return true;  299                 }  300                 return false;  301             }  302             else  303             {  304                 for (int i = 0; i < 1; )  305                 {  306                     try  307                     {  308                         foreach (var item in m_lstAnchors)  309                         {  310                             if (m_lstAnchors[item.Key] != null && !m_lstAnchors[item.Key].IsDisposed)  311                             {  312                                 m_lstAnchors[item.Key].Close();  313                             }  314                         }  315                     }  316                     catch  317                     {  318                         continue;  319                     }  320                     i++;  321                 }  322                 m_lstAnchors.Clear();  323                 return true;  324             }  325         }  326   327         /// <summary>  328         /// Determines whether [has in cache child] [the specified menu].  329         /// </summary>  330         /// <param name="menu">The menu.</param>  331         /// <returns><c>true</c> if [has in cache child] [the specified menu]; otherwise, <c>false</c>.</returns>  332         private bool HasInCacheChild(NavigationMenuItem menu)  333         {  334             foreach (var item in m_lstAnchors)  335             {  336                 if (item.Key == menu)  337                 {  338                     return true;  339                 }  340                 else  341                 {  342                     if (item.Key.Items != null)  343                     {  344                         if (item.Key.Items.Contains(menu))  345                             return true;  346                     }  347                 }  348             }  349             return false;  350         }  351   352         /// <summary>  353         /// Closes the list.  354         /// </summary>  355         /// <param name="menu">The menu.</param>  356         private void CloseList(NavigationMenuItem menu)  357         {  358             if (menu.Items != null)  359             {  360                 foreach (var item in menu.Items)  361                 {  362                     CloseList(item);  363                     if (m_lstAnchors.ContainsKey(item))  364                     {  365                         if (m_lstAnchors[item] != null && !m_lstAnchors[item].IsDisposed)  366                         {  367                             m_lstAnchors[item].Close();  368                             m_lstAnchors[item] = null;  369                             m_lstAnchors.Remove(item);  370                         }  371                     }  372                 }  373             }  374         }  375   376         /// <summary>  377         /// Shows the more menu.  378         /// </summary>  379         /// <param name="lbl">The label.</param>  380         private void ShowMoreMenu(Label lbl)  381         {  382             var menu = (NavigationMenuItem)lbl.Tag;  383             if (CheckShow(menu))  384             {  385                 if (menu.Items != null && menu.Items.Length > 0)  386                 {  387                     Panel panel = new Panel();  388                     panel.BackColor = Color.White;  389                     panel.Paint += panel_Paint;  390                     panel.Padding = new System.Windows.Forms.Padding(1);  391                     Size size = GetItemsSize(menu.Items);  392                     var height = size.Height * menu.Items.Length + 2;  393                     height += menu.Items.Count(p => p.HasSplitLintAtTop);//分割线  394                     if (size.Width < lbl.Width)  395                         size.Width = lbl.Width;  396                     panel.Size = new Size(size.Width, height);  397   398                     foreach (var item in menu.Items)  399                     {  400                         if (item.HasSplitLintAtTop)  401                         {  402                             UCSplitLine_H line = new UCSplitLine_H();  403                             line.Dock = DockStyle.Top;  404                             panel.Controls.Add(line);  405                             line.BringToFront();  406                         }  407                         Label _lbl = new Label();  408                         _lbl.Font = Font;  409                         _lbl.ForeColor = this.BackColor;  410                         _lbl.AutoSize = false;  411                         _lbl.TextAlign = ContentAlignment.MiddleCenter;  412                         _lbl.Height = size.Height;  413                         _lbl.Text = item.Text;  414                         _lbl.Dock = DockStyle.Top;  415                         _lbl.BringToFront();  416                         _lbl.Paint += lbl_Paint;  417                         _lbl.MouseEnter += lbl_MouseEnter;  418                         _lbl.Tag = item;  419                         _lbl.Click += lbl_Click;  420                         _lbl.Size = new System.Drawing.Size(size.Width, size.Height);  421                         panel.Controls.Add(_lbl);  422                         _lbl.BringToFront();  423                     }  424                     Point point = Point.Empty;  425   426                     if (menu.ParentItem != null)  427                     {  428                         Point p = lbl.Parent.PointToScreen(lbl.Location);  429                         if (p.X + lbl.Width + panel.Width > Screen.PrimaryScreen.Bounds.Width)  430                         {  431                             point = new Point(-1 * panel.Width - 2, -1 * lbl.Height);  432                         }  433                         else  434                         {  435                             point = new Point(panel.Width + 2, -1 * lbl.Height);  436                         }  437                     }  438                     m_lstAnchors[menu] = new FrmAnchor(lbl, panel, point);  439                     m_lstAnchors[menu].FormClosing += UCNavigationMenu_FormClosing;  440                     m_lstAnchors[menu].Show();  441                     m_lstAnchors[menu].Size = new Size(size.Width, height);  442                 }  443             }  444   445         }  446   447         /// <summary>  448         /// Handles the FormClosing event of the UCNavigationMenu control.  449         /// </summary>  450         /// <param name="sender">The source of the event.</param>  451         /// <param name="e">The <see cref="FormClosingEventArgs"/> instance containing the event data.</param>  452         void UCNavigationMenu_FormClosing(object sender, FormClosingEventArgs e)  453         {  454             FrmAnchor frm = sender as FrmAnchor;  455             if (m_lstAnchors.ContainsValue(frm))  456             {  457                 foreach (var item in m_lstAnchors)  458                 {  459                     if (item.Value == frm)  460                     {  461                         m_lstAnchors.Remove(item.Key);  462                         return;  463                     }  464                 }  465             }  466         }  467   468         /// <summary>  469         /// Handles the Paint event of the panel control.  470         /// </summary>  471         /// <param name="sender">The source of the event.</param>  472         /// <param name="e">The <see cref="PaintEventArgs"/> instance containing the event data.</param>  473         void panel_Paint(object sender, PaintEventArgs e)  474         {  475             e.Graphics.SetGDIHigh();  476             Rectangle rect = new Rectangle(0, 0, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);  477             var path = rect.CreateRoundedRectanglePath(2);  478             e.Graphics.DrawPath(new Pen(new SolidBrush(LineColors.Light)), path);  479         }  480   481   482   483         /// <summary>  484         /// Gets the size of the items.  485         /// </summary>  486         /// <param name="items">The items.</param>  487         /// <returns>Size.</returns>  488         private Size GetItemsSize(NavigationMenuItem[] items)  489         {  490             Size size = Size.Empty;  491             if (items != null && items.Length > 0)  492             {  493                 using (var g = this.CreateGraphics())  494                 {  495                     foreach (NavigationMenuItem item in items)  496                     {  497                         var s = g.MeasureString(item.Text, Font);  498                         if (s.Width + 25 > size.Width)  499                         {  500                             size.Width = (int)s.Width + 25;  501                         }  502                         if (s.Height + 10 > size.Height)  503                         {  504                             size.Height = (int)s.Height + 10;  505                         }  506                     }  507                 }  508             }  509             return size;  510         }  511   512   513         /// <summary>  514         /// Handles the Paint event of the lbl control.  515         /// </summary>  516         /// <param name="sender">The source of the event.</param>  517         /// <param name="e">The <see cref="PaintEventArgs"/> instance containing the event data.</param>  518         void lbl_Paint(object sender, PaintEventArgs e)  519         {  520             Label lbl = sender as Label;  521             if (lbl.Tag != null)  522             {  523                 var menu = (NavigationMenuItem)lbl.Tag;  524                 e.Graphics.SetGDIHigh();  525                 if (menu.ParentItem == null)//顶级节点支持图标和角标  526                 {  527                     if (menu.ShowTip)  528                     {  529                         if (!string.IsNullOrEmpty(menu.TipText))  530                         {  531                             var rect = new Rectangle(lbl.Width - 25, lbl.Height / 2 - 10, 20, 20);  532                             var path = rect.CreateRoundedRectanglePath(5);  533                             e.Graphics.FillPath(new SolidBrush(tipColor), path);  534                             e.Graphics.DrawString(menu.TipText, new Font("微软雅黑", 8f), new SolidBrush(Color.White), rect, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });  535                         }  536                         else  537                         {  538                             e.Graphics.FillEllipse(new SolidBrush(tipColor), new Rectangle(lbl.Width - 20, lbl.Height / 2 - 10, 10, 10));  539                         }  540                     }  541                     if (menu.Icon != null)  542                     {  543                         e.Graphics.DrawImage(menu.Icon, new Rectangle(1, (lbl.Height - 25) / 2, 25, 25), 0, 0, menu.Icon.Width, menu.Icon.Height, GraphicsUnit.Pixel);  544                     }  545                 }  546                 if (menu.ParentItem != null && menu.Items != null && menu.Items.Length > 0)  547                 {  548                     ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(this.BackColor), new Point(lbl.Width - 11, (lbl.Height - 5) / 2), 5, GraphDirection.Rightward);  549                 }  550             }  551         }  552     }  553 }
View Code

 

最后的话

如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!