入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
Install-Package HZH_Controls
https://www.cnblogs.com/bfyx/p/11364884.html
依然用GDI+,请自行百度了解
添加一个类UCArrow,继承UserControl
添加枚举,控制方向
1 /// <summary>
2 /// Enum ArrowDirection
3 /// </summary>
4 public enum ArrowDirection
5 {
6 /// <summary>
7 /// The left
8 /// </summary>
9 Left,
10 /// <summary>
11 /// The right
12 /// </summary>
13 Right,
14 /// <summary>
15 /// The top
16 /// </summary>
17 Top,
18 /// <summary>
19 /// The bottom
20 /// </summary>
21 Bottom,
22 /// <summary>
23 /// The left right
24 /// </summary>
25 Left_Right,
26 /// <summary>
27 /// The top bottom
28 /// </summary>
29 Top_Bottom
30 }
一些属性
1 /// <summary>
2 /// The arrow color
3 /// </summary>
4 private Color arrowColor = Color.FromArgb(255, 77, 59);
5
6 /// <summary>
7 /// Gets or sets the color of the arrow.
8 /// </summary>
9 /// <value>The color of the arrow.</value>
10 [Description("箭头颜色"), Category("自定义")]
11 public Color ArrowColor
12 {
13 get { return arrowColor; }
14 set
15 {
16 arrowColor = value;
17 Refresh();
18 }
19 }
20
21 /// <summary>
22 /// The border color
23 /// </summary>
24 private Color? borderColor = null;
25
26 /// <summary>
27 /// Gets or sets the color of the border.
28 /// </summary>
29 /// <value>The color of the border.</value>
30 [Description("箭头边框颜色,为空则无边框"), Category("自定义")]
31 public Color? BorderColor
32 {
33 get { return borderColor; }
34 set
35 {
36 borderColor = value;
37 Refresh();
38 }
39 }
40
41 /// <summary>
42 /// The direction
43 /// </summary>
44 private ArrowDirection direction = ArrowDirection.Right;
45
46 /// <summary>
47 /// Gets or sets the direction.
48 /// </summary>
49 /// <value>The direction.</value>
50 [Description("箭头方向"), Category("自定义")]
51 public ArrowDirection Direction
52 {
53 get { return direction; }
54 set
55 {
56 direction = value;
57 ResetPath();
58 Refresh();
59 }
60 }
61 /// <summary>
62 /// 获取或设置控件显示的文字的字体。
63 /// </summary>
64 /// <value>The font.</value>
65 /// <PermissionSet>
66 /// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
67 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
68 /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
69 /// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
70 /// </PermissionSet>
71 public override Font Font
72 {
73 get
74 {
75 return base.Font;
76 }
77 set
78 {
79 base.Font = value;
80 Refresh();
81 }
82 }
83 /// <summary>
84 /// 获取或设置控件的前景色。
85 /// </summary>
86 /// <value>The color of the fore.</value>
87 /// <PermissionSet>
88 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
89 /// </PermissionSet>
90 public override Color ForeColor
91 {
92 get
93 {
94 return base.ForeColor;
95 }
96 set
97 {
98 base.ForeColor = value;
99 Refresh();
100 }
101 }
102 /// <summary>
103 /// The text
104 /// </summary>
105 private string text;
106 /// <summary>
107 /// Gets or sets the text.
108 /// </summary>
109 /// <value>The text.</value>
110 [Bindable(true)]
111 [Browsable(true)]
112 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
113 [EditorBrowsable(EditorBrowsableState.Always)]
114 [Localizable(true)]
115 [Description("箭头文字"), Category("自定义")]
116 public override string Text
117 {
118 get
119 {
120 return text;
121 }
122 set
123 {
124 text = value;
125 Refresh();
126 }
127 }
128 /// <summary>
129 /// The m path
130 /// </summary>
131 GraphicsPath m_path;
根据方向和大小设置path
1 private void ResetPath()
2 {
3 Point[] ps = null;
4 switch (direction)
5 {
6 case ArrowDirection.Left:
7 ps = new Point[]
8 {
9 new Point(0,this.Height/2),
10 new Point(40,0),
11 new Point(40,this.Height/4),
12 new Point(this.Width-1,this.Height/4),
13 new Point(this.Width-1,this.Height-this.Height/4),
14 new Point(40,this.Height-this.Height/4),
15 new Point(40,this.Height),
16 new Point(0,this.Height/2)
17 };
18 break;
19 case ArrowDirection.Right:
20 ps = new Point[]
21 {
22 new Point(0,this.Height/4),
23 new Point(this.Width-40,this.Height/4),
24 new Point(this.Width-40,0),
25 new Point(this.Width-1,this.Height/2),
26 new Point(this.Width-40,this.Height),
27 new Point(this.Width-40,this.Height-this.Height/4),
28 new Point(0,this.Height-this.Height/4),
29 new Point(0,this.Height/4)
30 };
31 break;
32 case ArrowDirection.Top:
33 ps = new Point[]
34 {
35 new Point(this.Width/2,0),
36 new Point(this.Width,40),
37 new Point(this.Width-this.Width/4,40),
38 new Point(this.Width-this.Width/4,this.Height-1),
39 new Point(this.Width/4,this.Height-1),
40 new Point(this.Width/4,40),
41 new Point(0,40),
42 new Point(this.Width/2,0),
43 };
44 break;
45 case ArrowDirection.Bottom:
46 ps = new Point[]
47 {
48 new Point(this.Width-this.Width/4,0),
49 new Point(this.Width-this.Width/4,this.Height-40),
50 new Point(this.Width,this.Height-40),
51 new Point(this.Width/2,this.Height-1),
52 new Point(0,this.Height-40),
53 new Point(this.Width/4,this.Height-40),
54 new Point(this.Width/4,0),
55 new Point(this.Width-this.Width/4,0),
56 };
57 break;
58 case ArrowDirection.Left_Right:
59 ps = new Point[]
60 {
61 new Point(0,this.Height/2),
62 new Point(40,0),
63 new Point(40,this.Height/4),
64 new Point(this.Width-40,this.Height/4),
65 new Point(this.Width-40,0),
66 new Point(this.Width-1,this.Height/2),
67 new Point(this.Width-40,this.Height),
68 new Point(this.Width-40,this.Height-this.Height/4),
69 new Point(40,this.Height-this.Height/4),
70 new Point(40,this.Height),
71 new Point(0,this.Height/2),
72 };
73 break;
74 case ArrowDirection.Top_Bottom:
75 ps = new Point[]
76 {
77 new Point(this.Width/2,0),
78 new Point(this.Width,40),
79 new Point(this.Width-this.Width/4,40),
80 new Point(this.Width-this.Width/4,this.Height-40),
81 new Point(this.Width,this.Height-40),
82 new Point(this.Width/2,this.Height-1),
83 new Point(0,this.Height-40),
84 new Point(this.Width/4,this.Height-40),
85 new Point(this.Width/4,40),
86 new Point(0,40),
87 new Point(this.Width/2,0),
88 };
89 break;
90 }
91 m_path = new GraphicsPath();
92 m_path.AddLines(ps);
93 m_path.CloseAllFigures();
94 }
重绘
1 protected override void OnPaint(PaintEventArgs e)
2 {
3 base.OnPaint(e);
4 var g = e.Graphics;
5 g.SetGDIHigh();
6
7 g.FillPath(new SolidBrush(arrowColor), m_path);
8
9 if (borderColor != null && borderColor != Color.Empty)
10 g.DrawPath(new Pen(new SolidBrush(borderColor.Value)), m_path);
11 if (!string.IsNullOrEmpty(text))
12 {
13 var size = g.MeasureString(Text, Font);
14 g.DrawString(Text, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / 2, (this.Height - size.Height) / 2));
15 }
16 }
完整代码
1 // ***********************************************************************
2 // Assembly : HZH_Controls
3 // Created : 2019-09-10
4 //
5 // ***********************************************************************
6 // <copyright file="UCArrow.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.Linq;
19 using System.Text;
20 using System.Windows.Forms;
21 using System.Drawing;
22 using System.Drawing.Drawing2D;
23 using System.ComponentModel;
24
25 namespace HZH_Controls.Controls
26 {
27 /// <summary>
28 /// Class UCArrow.
29 /// Implements the <see cref="System.Windows.Forms.UserControl" />
30 /// </summary>
31 /// <seealso cref="System.Windows.Forms.UserControl" />
32 public class UCArrow : UserControl
33 {
34 /// <summary>
35 /// The arrow color
36 /// </summary>
37 private Color arrowColor = Color.FromArgb(255, 77, 59);
38
39 /// <summary>
40 /// Gets or sets the color of the arrow.
41 /// </summary>
42 /// <value>The color of the arrow.</value>
43 [Description("箭头颜色"), Category("自定义")]
44 public Color ArrowColor
45 {
46 get { return arrowColor; }
47 set
48 {
49 arrowColor = value;
50 Refresh();
51 }
52 }
53
54 /// <summary>
55 /// The border color
56 /// </summary>
57 private Color? borderColor = null;
58
59 /// <summary>
60 /// Gets or sets the color of the border.
61 /// </summary>
62 /// <value>The color of the border.</value>
63 [Description("箭头边框颜色,为空则无边框"), Category("自定义")]
64 public Color? BorderColor
65 {
66 get { return borderColor; }
67 set
68 {
69 borderColor = value;
70 Refresh();
71 }
72 }
73
74 /// <summary>
75 /// The direction
76 /// </summary>
77 private ArrowDirection direction = ArrowDirection.Right;
78
79 /// <summary>
80 /// Gets or sets the direction.
81 /// </summary>
82 /// <value>The direction.</value>
83 [Description("箭头方向"), Category("自定义")]
84 public ArrowDirection Direction
85 {
86 get { return direction; }
87 set
88 {
89 direction = value;
90 ResetPath();
91 Refresh();
92 }
93 }
94 /// <summary>
95 /// 获取或设置控件显示的文字的字体。
96 /// </summary>
97 /// <value>The font.</value>
98 /// <PermissionSet>
99 /// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
100 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
101 /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
102 /// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
103 /// </PermissionSet>
104 public override Font Font
105 {
106 get
107 {
108 return base.Font;
109 }
110 set
111 {
112 base.Font = value;
113 Refresh();
114 }
115 }
116 /// <summary>
117 /// 获取或设置控件的前景色。
118 /// </summary>
119 /// <value>The color of the fore.</value>
120 /// <PermissionSet>
121 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
122 /// </PermissionSet>
123 public override Color ForeColor
124 {
125 get
126 {
127 return base.ForeColor;
128 }
129 set
130 {
131 base.ForeColor = value;
132 Refresh();
133 }
134 }
135 /// <summary>
136 /// The text
137 /// </summary>
138 private string text;
139 /// <summary>
140 /// Gets or sets the text.
141 /// </summary>
142 /// <value>The text.</value>
143 [Bindable(true)]
144 [Browsable(true)]
145 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
146 [EditorBrowsable(EditorBrowsableState.Always)]
147 [Localizable(true)]
148 [Description("箭头文字"), Category("自定义")]
149 public override string Text
150 {
151 get
152 {
153 return text;
154 }
155 set
156 {
157 text = value;
158 Refresh();
159 }
160 }
161 /// <summary>
162 /// The m path
163 /// </summary>
164 GraphicsPath m_path;
165 /// <summary>
166 /// Initializes a new instance of the <see cref="UCArrow"/> class.
167 /// </summary>
168 public UCArrow()
169 {
170 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
171 this.SetStyle(ControlStyles.DoubleBuffer, true);
172 this.SetStyle(ControlStyles.ResizeRedraw, true);
173 this.SetStyle(ControlStyles.Selectable, true);
174 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
175 this.SetStyle(ControlStyles.UserPaint, true);
176 this.ForeColor = Color.White;
177 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
178 this.SizeChanged += UCArrow_SizeChanged;
179 this.Size = new Size(100, 50);
180 }
181
182 /// <summary>
183 /// Handles the SizeChanged event of the UCArrow control.
184 /// </summary>
185 /// <param name="sender">The source of the event.</param>
186 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
187 void UCArrow_SizeChanged(object sender, EventArgs e)
188 {
189 ResetPath();
190 }
191
192 /// <summary>
193 /// Resets the path.
194 /// </summary>
195 private void ResetPath()
196 {
197 Point[] ps = null;
198 switch (direction)
199 {
200 case ArrowDirection.Left:
201 ps = new Point[]
202 {
203 new Point(0,this.Height/2),
204 new Point(40,0),
205 new Point(40,this.Height/4),
206 new Point(this.Width-1,this.Height/4),
207 new Point(this.Width-1,this.Height-this.Height/4),
208 new Point(40,this.Height-this.Height/4),
209 new Point(40,this.Height),
210 new Point(0,this.Height/2)
211 };
212 break;
213 case ArrowDirection.Right:
214 ps = new Point[]
215 {
216 new Point(0,this.Height/4),
217 new Point(this.Width-40,this.Height/4),
218 new Point(this.Width-40,0),
219 new Point(this.Width-1,this.Height/2),
220 new Point(this.Width-40,this.Height),
221 new Point(this.Width-40,this.Height-this.Height/4),
222 new Point(0,this.Height-this.Height/4),
223 new Point(0,this.Height/4)
224 };
225 break;
226 case ArrowDirection.Top:
227 ps = new Point[]
228 {
229 new Point(this.Width/2,0),
230 new Point(this.Width,40),
231 new Point(this.Width-this.Width/4,40),
232 new Point(this.Width-this.Width/4,this.Height-1),
233 new Point(this.Width/4,this.Height-1),
234 new Point(this.Width/4,40),
235 new Point(0,40),
236 new Point(this.Width/2,0),
237 };
238 break;
239 case ArrowDirection.Bottom:
240 ps = new Point[]
241 {
242 new Point(this.Width-this.Width/4,0),
243 new Point(this.Width-this.Width/4,this.Height-40),
244 new Point(this.Width,this.Height-40),
245 new Point(this.Width/2,this.Height-1),
246 new Point(0,this.Height-40),
247 new Point(this.Width/4,this.Height-40),
248 new Point(this.Width/4,0),
249 new Point(this.Width-this.Width/4,0),
250 };
251 break;
252 case ArrowDirection.Left_Right:
253 ps = new Point[]
254 {
255 new Point(0,this.Height/2),
256 new Point(40,0),
257 new Point(40,this.Height/4),
258 new Point(this.Width-40,this.Height/4),
259 new Point(this.Width-40,0),
260 new Point(this.Width-1,this.Height/2),
261 new Point(this.Width-40,this.Height),
262 new Point(this.Width-40,this.Height-this.Height/4),
263 new Point(40,this.Height-this.Height/4),
264 new Point(40,this.Height),
265 new Point(0,this.Height/2),
266 };
267 break;
268 case ArrowDirection.Top_Bottom:
269 ps = new Point[]
270 {
271 new Point(this.Width/2,0),
272 new Point(this.Width,40),
273 new Point(this.Width-this.Width/4,40),
274 new Point(this.Width-this.Width/4,this.Height-40),
275 new Point(this.Width,this.Height-40),
276 new Point(this.Width/2,this.Height-1),
277 new Point(0,this.Height-40),
278 new Point(this.Width/4,this.Height-40),
279 new Point(this.Width/4,40),
280 new Point(0,40),
281 new Point(this.Width/2,0),
282 };
283 break;
284 }
285 m_path = new GraphicsPath();
286 m_path.AddLines(ps);
287 m_path.CloseAllFigures();
288 }
289
290 /// <summary>
291 /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
292 /// </summary>
293 /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
294 protected override void OnPaint(PaintEventArgs e)
295 {
296 base.OnPaint(e);
297 var g = e.Graphics;
298 g.SetGDIHigh();
299
300 g.FillPath(new SolidBrush(arrowColor), m_path);
301
302 if (borderColor != null && borderColor != Color.Empty)
303 g.DrawPath(new Pen(new SolidBrush(borderColor.Value)), m_path);
304 if (!string.IsNullOrEmpty(text))
305 {
306 var size = g.MeasureString(Text, Font);
307 g.DrawString(Text, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / 2, (this.Height - size.Height) / 2));
308 }
309 }
310 }
311
312 /// <summary>
313 /// Enum ArrowDirection
314 /// </summary>
315 public enum ArrowDirection
316 {
317 /// <summary>
318 /// The left
319 /// </summary>
320 Left,
321 /// <summary>
322 /// The right
323 /// </summary>
324 Right,
325 /// <summary>
326 /// The top
327 /// </summary>
328 Top,
329 /// <summary>
330 /// The bottom
331 /// </summary>
332 Bottom,
333 /// <summary>
334 /// The left right
335 /// </summary>
336 Left_Right,
337 /// <summary>
338 /// The top bottom
339 /// </summary>
340 Top_Bottom
341 }
342 }