前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control>
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492  <https://shang.qq.com/wpa/qunwpa? 
idkey=6e08741ef16fe53bf0314c1c9e336c4f626047943a8b76bac062361bab6b4f8d>
目录
https://www.cnblogs.com/bfyx/p/11364884.html 
<https://www.cnblogs.com/bfyx/p/11364884.html>
准备工作
GDI+画的,不了解GDI+可以百度了解下先
开始
添加一个用户控件,命名UCCrumbNavigation
提供属性
 1 private Color m_navColor = Color.FromArgb(100, 100, 100);  2  3 public 
Color NavColor 4  {  5 get { return m_navColor; }  6 set  7  {  8 if (value == 
Color.Empty || value == Color.Transparent)  9 return; 10 m_navColor = value; 11 
 Refresh();12  } 13  } 14 15 16 private string[] m_navigations = new string[] { 
"目录1", "目录2", "目录3" }; 17  GraphicsPath[] m_paths; 18 public string[] 
Navigations19  { 20 get { return m_navigations; } 21 set 22  { 23 m_navigations 
= value; 24 if (value == null) 25 m_paths = new GraphicsPath[0]; 26 else 27 
m_paths =new GraphicsPath[value.Length]; 28  Refresh(); 29  } 30  } 31 32 public
override Font Font 33  { 34 get 35  { 36 return base.Font; 37  } 38 set 39  { 40
base.Font = value; 41  Refresh(); 42  } 43  } 44 45 public override 
System.Drawing.Color ForeColor46  { 47 get 48  { 49 return base.ForeColor; 50  }
51 set 52  { 53 base.ForeColor = value; 54  Refresh(); 55  } 56 } 
重绘
 1 protected override void OnPaint(PaintEventArgs e)  2  {  3 base.OnPaint(e); 
 4  5 if (m_navigations != null && m_navigations.Length > 0)  6  {  7 var g = 
e.Graphics; 8 int intLastX = 0;  9 int intLength = m_navigations.Length; 10 for 
(int i = 0; i < m_navigations.Length; i++) 11  { 12 GraphicsPath path = new 
GraphicsPath();13 string strText = m_navigations[i]; 14 System.Drawing.SizeF 
sizeF = g.MeasureString(strText.Replace(" ", "A"), Font); 15 int intTextWidth = 
(int)sizeF.Width + 1; 16 path.AddLine(new Point(intLastX + 1, 1), new 
Point(intLastX +1 + (i == 0 ? 0 : 10) + intTextWidth, 1)); 17 18 //if (i != 
(intLength - 1))19 //{ 20 path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 10
) + intTextWidth,1), new Point(intLastX + 1 + (i == 0 ? 0 : 10) + intTextWidth +
10, this.Height / 2)); 21 path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 10
) + intTextWidth +10, this.Height / 2), new Point(intLastX + 1 + (i == 0 ? 0 : 
10) + intTextWidth - 1, this.Height - 1)); 22 //} 23 //else 24 //{ 25 // 
path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 10) + intTextWidth, 1), new 
Point(intLastX + 1 + (i == 0 ? 0 : 10) + intTextWidth, this.Height - 1));26 //} 
27 28 path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 10) + intTextWidth, 
this.Height - 1), new Point(intLastX + 1, this.Height - 1)); 29 30 if (i != 0) 
31  { 32 path.AddLine(new Point(intLastX, this.Height - 1), new Point(intLastX +
1 + 10, this.Height / 2)); 33 path.AddLine(new Point(intLastX + 1 + 10, this
.Height /2), new Point(intLastX + 1, 1)); 34  } 35 else 36  { 37 path.AddLine(
new Point(intLastX + 1, this.Height - 1), new Point(intLastX + 1, 1)); 38  } 39 
g.FillPath(new SolidBrush(m_navColor), path); 40 41 g.DrawString(strText, this
.Font,new SolidBrush(this.ForeColor), new PointF(intLastX + 2 + (i == 0 ? 0 : 10
), (this.Height - sizeF.Height) / 2 + 1)); 42 m_paths[i] = path; 43 intLastX += 
((i ==0 ? 0 : 10) + intTextWidth + (i == (intLength - 1) ? 0 : 10)); 44  } 45  }
46 47 } 
处理一下点击事件
 1 void UCCrumbNavigation_MouseDown(object sender, MouseEventArgs e)  2  {  3 
if (!DesignMode)  4  {  5 if (m_paths != null && m_paths.Length > 0)  6  {  7 
for (int i = 0; i < m_paths.Length; i++)  8  {  9 if 
(m_paths[i].IsVisible(e.Location))10  { 11 
HZH_Controls.Forms.FrmTips.ShowTipsSuccess(this.FindForm(), m_navigations[i]); 
12  } 13  } 14  } 15  } 16 } 
完整代码如下
 1 using System;  2 using System.Collections.Generic;  3 using 
System.ComponentModel; 4 using System.Drawing;  5 using System.Data;  6 using 
System.Linq; 7 using System.Text;  8 using System.Windows.Forms;  9 using 
System.Drawing.Drawing2D; 10  11 namespace HZH_Controls.Controls  12 {  13 
public partial class UCCrumbNavigation : UserControl  14  {  15 private Color 
m_navColor = Color.FromArgb(100, 100, 100);  16  17 public Color NavColor  18  {
 19 get { return m_navColor; }  20 set  21  {  22 if (value == Color.Empty || 
value == Color.Transparent)  23 return;  24 m_navColor = value;  25  Refresh(); 
 26  }  27  }  28  29  30 private string[] m_navigations = new string[] { "目录1",
"目录2", "目录3" };  31  GraphicsPath[] m_paths;  32 public string[] Navigations  33
 { 34 get { return m_navigations; }  35 set  36  {  37 m_navigations = value;  
38 if (value == null)  39 m_paths = new GraphicsPath[0];  40 else  41 m_paths = 
new GraphicsPath[value.Length];  42  Refresh();  43  }  44  }  45  46 public 
override Font Font  47  {  48 get  49  {  50 return base.Font;  51  }  52 set  
53  {  54 base.Font = value;  55  Refresh();  56  }  57  }  58  59 public 
override System.Drawing.Color ForeColor  60  {  61 get  62  {  63 return base
.ForeColor; 64  }  65 set  66  {  67 base.ForeColor = value;  68  Refresh();  69
 } 70  }  71  72 public UCCrumbNavigation()  73  {  74  InitializeComponent();  
75 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  76 this
.SetStyle(ControlStyles.DoubleBuffer,true);  77 this
.SetStyle(ControlStyles.ResizeRedraw,true);  78 this
.SetStyle(ControlStyles.Selectable,true);  79 this
.SetStyle(ControlStyles.SupportsTransparentBackColor,true);  80 this
.SetStyle(ControlStyles.UserPaint,true);  81 this.MouseDown += 
UCCrumbNavigation_MouseDown; 82  }  83  84 void UCCrumbNavigation_MouseDown(
object sender, MouseEventArgs e)  85  {  86 if (!DesignMode)  87  {  88 if 
(m_paths !=null && m_paths.Length > 0)  89  {  90 for (int i = 0; i < 
m_paths.Length; i++)  91  {  92 if (m_paths[i].IsVisible(e.Location))  93  {  94
 HZH_Controls.Forms.FrmTips.ShowTipsSuccess(this.FindForm(), m_navigations[i]); 
 95  }  96  }  97  }  98  }  99  } 100 101 protected override void 
OnPaint(PaintEventArgs e)102  { 103 base.OnPaint(e); 104 105 if (m_navigations 
!=null && m_navigations.Length > 0) 106  { 107 var g = e.Graphics; 108 int 
intLastX =0; 109 int intLength = m_navigations.Length; 110 for (int i = 0; i < 
m_navigations.Length; i++) 111  { 112 GraphicsPath path = new GraphicsPath(); 
113 string strText = m_navigations[i]; 114 System.Drawing.SizeF sizeF = 
g.MeasureString(strText.Replace(" ", "A"), Font); 115 int intTextWidth = (int
)sizeF.Width +1; 116 path.AddLine(new Point(intLastX + 1, 1), new 
Point(intLastX +1 + (i == 0 ? 0 : 10) + intTextWidth, 1)); 117 118 //if (i != 
(intLength - 1))119 //{ 120 path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 
10) + intTextWidth, 1), new Point(intLastX + 1 + (i == 0 ? 0 : 10) + 
intTextWidth +10, this.Height / 2)); 121 path.AddLine(new Point(intLastX + 1 + 
(i ==0 ? 0 : 10) + intTextWidth + 10, this.Height / 2), new Point(intLastX + 1 
+ (i ==0 ? 0 : 10) + intTextWidth - 1, this.Height - 1)); 122 //} 123 //else 124
//{ 125 // path.AddLine(new Point(intLastX + 1 + (i == 0 ? 0 : 10) + 
intTextWidth, 1), new Point(intLastX + 1 + (i == 0 ? 0 : 10) + intTextWidth, 
this.Height - 1));126 //} 127 128 path.AddLine(new Point(intLastX + 1 + (i == 0 
?0 : 10) + intTextWidth, this.Height - 1), new Point(intLastX + 1, this.Height -
1)); 129 130 if (i != 0) 131  { 132 path.AddLine(new Point(intLastX, this
.Height -1), new Point(intLastX + 1 + 10, this.Height / 2)); 133 path.AddLine(
new Point(intLastX + 1 + 10, this.Height / 2), new Point(intLastX + 1, 1)); 134 
 }135 else 136  { 137 path.AddLine(new Point(intLastX + 1, this.Height - 1), new
 Point(intLastX +1, 1)); 138  } 139 g.FillPath(new SolidBrush(m_navColor), 
path);140 141 g.DrawString(strText, this.Font, new SolidBrush(this.ForeColor), 
new PointF(intLastX + 2 + (i == 0 ? 0 : 10), (this.Height - sizeF.Height) / 2 + 
1)); 142 m_paths[i] = path; 143 intLastX += ((i == 0 ? 0 : 10) + intTextWidth + 
(i == (intLength -1) ? 0 : 10)); 144  } 145  } 146 147  } 148  } 149 } View Code
 1 namespace HZH_Controls.Controls  2 {  3 partial class UCCrumbNavigation  4  {
 5 /// <summary>  6 /// 必需的设计器变量。  7 /// </summary>  8 private 
System.ComponentModel.IContainer components =null;  9 10 /// <summary> 11 /// 
清理所有正在使用的资源。12 /// </summary> 13 /// <param name="disposing">如果应释放托管资源,为 
true;否则为 false。</param> 14 protected override void Dispose(bool disposing) 15  {
16 if (disposing && (components != null)) 17  { 18  components.Dispose(); 19  } 
20 base.Dispose(disposing); 21  } 22 23 #region 组件设计器生成的代码 24 25 /// <summary> 
26 /// 设计器支持所需的方法 - 不要 27 /// 使用代码编辑器修改此方法的内容。 28 /// </summary> 29 private void
 InitializeComponent()30  { 31 this.SuspendLayout(); 32 // 33 // 
UCCrumbNavigation34 // 35 this.AutoScaleMode = 
System.Windows.Forms.AutoScaleMode.None;36 this.Cursor = 
System.Windows.Forms.Cursors.Hand;37 this.ForeColor = 
System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((
int)(((byte)(224))))); 38 this.MinimumSize = new System.Drawing.Size(0, 25); 39 
this.Name = "UCCrumbNavigation"; 40 this.Size = new System.Drawing.Size(220, 25
);41 this.ResumeLayout(false); 42 43  } 44 45 #endregion 46 47 48  } 49 } View 
Code 
 
用处及效果
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control> 点个星 星吧
热门工具 换一换