主頁 > .NET開發 > (七十九)c#Winform自定義控制元件-導航選單-HZHControls

(七十九)c#Winform自定義控制元件-導航選單-HZHControls

2020-09-11 08:24:53 .NET開發

官網

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 width106         /// </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 ItemWidth115         {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  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  version="1" Unrestricted="true" /> 88         ///   <IPermission  version="1" Unrestricted="true" /> 89         ///   <IPermission  version="1" Flags="UnmanagedCode, ControlEvidence" /> 90         ///   <IPermission  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 anchors110         /// </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                         else30                         {31                             lbl.Dock = DockStyle.Left;32                         }33                         this.Controls.Add(lbl);34 35                         lbl.BringToFront();36                     }37 38 39                 }40             }41             finally42             {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                         else55                         {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             else24             {25                 for (int i = 0; i < 1; )26                 {27                     try28                     {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                     catch38                     {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                 else62                 {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 =https://www.cnblogs.com/bfyx/p/= 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                         else150                         {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:[email protected]  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  version="1" Unrestricted="true" />101         /// </PermissionSet>102         public override System.Drawing.Color ForeColor103         {104             get105             {106                 return base.ForeColor;107             }108             set109             {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  version="1" Unrestricted="true" />123         ///   <IPermission  version="1" Unrestricted="true" />124         ///   <IPermission  version="1" Flags="UnmanagedCode, ControlEvidence" />125         ///   <IPermission  version="1" Unrestricted="true" />126         /// </PermissionSet>127         public override Font Font128         {129             get130             {131                 return base.Font;132             }133             set134             {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 anchors145         /// </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 >= 2164                     };165                 }166             }167         }168 169         /// <summary>170         /// Reloads the menu.171         /// </summary>172         private void ReloadMenu()173         {174             try175             {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                         else201                         {202                             lbl.Dock = DockStyle.Left;203                         }204                         this.Controls.Add(lbl);205 206                         lbl.BringToFront();207                     }208 209 210                 }211             }212             finally213             {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                         try238                         {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                 else254                 {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             else303             {304                 for (int i = 0; i < 1; )305                 {306                     try307                     {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                     catch317                     {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                 else341                 {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                         else434                         {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 =https://www.cnblogs.com/bfyx/p/= 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                         else537                         {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 點個星星吧

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/4904.html

標籤:WinForm

上一篇:Winform中設定ZedGraph滑鼠焦點位置畫出十字線并在滑鼠移出時十字線消失

下一篇:(八十)c#Winform自定義控制元件-分割線標簽-HZHControls

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more