zoukankan      html  css  js  c++  java
  • (七十九)c#Winform自定义控件-导航菜单-HZHControls

    官网

    http://www.hzhcontrols.com

    前提

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

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

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

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

    欢迎前来交流探讨: 企鹅群568015492 企鹅群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 点个星星吧

  • 相关阅读:
    定义函数
    变量与常量
    字符串与格式化
    字符串与编码
    字符编码
    元组-tuple
    列表-list
    分支和循环
    润乾配置连接kingbase(金仓)数据库
    润乾报表在proxool应用下的数据源配置
  • 原文地址:https://www.cnblogs.com/bfyx/p/11639401.html
Copyright © 2011-2022 走看看