前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
目录
https://blog.csdn.net/kwwwvagaa/article/details/100586547
用处及效果
准备工作
依然用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 }
完整代码
// ***********************************************************************
// Assembly : HZH_Controls
// Created : 2019-09-10
//
// ***********************************************************************
// <copyright file="UCArrow.cs">
// Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
// </copyright>
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
namespace HZH_Controls.Controls
{
/// <summary>
/// Class UCArrow.
/// Implements the <see cref="System.Windows.Forms.UserControl" />
/// </summary>
/// <seealso cref="System.Windows.Forms.UserControl" />
public class UCArrow : UserControl
{
/// <summary>
/// The arrow color
/// </summary>
private Color arrowColor = Color.FromArgb(255, 77, 59);
/// <summary>
/// Gets or sets the color of the arrow.
/// </summary>
/// <value>The color of the arrow.</value>
[Description("箭头颜色"), Category("自定义")]
public Color ArrowColor
{
get { return arrowColor; }
set
{
arrowColor = value;
Refresh();
}
}
/// <summary>
/// The border color
/// </summary>
private Color? borderColor = null;
/// <summary>
/// Gets or sets the color of the border.
/// </summary>
/// <value>The color of the border.</value>
[Description("箭头边框颜色,为空则无边框"), Category("自定义")]
public Color? BorderColor
{
get { return borderColor; }
set
{
borderColor = value;
Refresh();
}
}
/// <summary>
/// The direction
/// </summary>
private ArrowDirection direction = ArrowDirection.Right;
/// <summary>
/// Gets or sets the direction.
/// </summary>
/// <value>The direction.</value>
[Description("箭头方向"), Category("自定义")]
public ArrowDirection Direction
{
get { return direction; }
set
{
direction = value;
ResetPath();
Refresh();
}
}
/// <summary>
/// 获取或设置控件显示的文字的字体。
/// </summary>
/// <value>The font.</value>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
/// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
Refresh();
}
}
/// <summary>
/// 获取或设置控件的前景色。
/// </summary>
/// <value>The color of the fore.</value>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
public override Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
Refresh();
}
}
/// <summary>
/// The text
/// </summary>
private string text;
/// <summary>
/// Gets or sets the text.
/// </summary>
/// <value>The text.</value>
[Bindable(true)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[EditorBrowsable(EditorBrowsableState.Always)]
[Localizable(true)]
[Description("箭头文字"), Category("自定义")]
public override string Text
{
get
{
return text;
}
set
{
text = value;
Refresh();
}
}
/// <summary>
/// The m path
/// </summary>
GraphicsPath m_path;
/// <summary>
/// Initializes a new instance of the <see cref="UCArrow"/> class.
/// </summary>
public UCArrow()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.ForeColor = Color.White;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.SizeChanged += UCArrow_SizeChanged;
this.Size = new Size(100, 50);
}
/// <summary>
/// Handles the SizeChanged event of the UCArrow control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
void UCArrow_SizeChanged(object sender, EventArgs e)
{
ResetPath();
}
/// <summary>
/// Resets the path.
/// </summary>
private void ResetPath()
{
Point[] ps = null;
switch (direction)
{
case ArrowDirection.Left:
ps = new Point[]
{
new Point(0,this.Height/2),
new Point(40,0),
new Point(40,this.Height/4),
new Point(this.Width-1,this.Height/4),
new Point(this.Width-1,this.Height-this.Height/4),
new Point(40,this.Height-this.Height/4),
new Point(40,this.Height),
new Point(0,this.Height/2)
};
break;
case ArrowDirection.Right:
ps = new Point[]
{
new Point(0,this.Height/4),
new Point(this.Width-40,this.Height/4),
new Point(this.Width-40,0),
new Point(this.Width-1,this.Height/2),
new Point(this.Width-40,this.Height),
new Point(this.Width-40,this.Height-this.Height/4),
new Point(0,this.Height-this.Height/4),
new Point(0,this.Height/4)
};
break;
case ArrowDirection.Top:
ps = new Point[]
{
new Point(this.Width/2,0),
new Point(this.Width,40),
new Point(this.Width-this.Width/4,40),
new Point(this.Width-this.Width/4,this.Height-1),
new Point(this.Width/4,this.Height-1),
new Point(this.Width/4,40),
new Point(0,40),
new Point(this.Width/2,0),
};
break;
case ArrowDirection.Bottom:
ps = new Point[]
{
new Point(this.Width-this.Width/4,0),
new Point(this.Width-this.Width/4,this.Height-40),
new Point(this.Width,this.Height-40),
new Point(this.Width/2,this.Height-1),
new Point(0,this.Height-40),
new Point(this.Width/4,this.Height-40),
new Point(this.Width/4,0),
new Point(this.Width-this.Width/4,0),
};
break;
case ArrowDirection.Left_Right:
ps = new Point[]
{
new Point(0,this.Height/2),
new Point(40,0),
new Point(40,this.Height/4),
new Point(this.Width-40,this.Height/4),
new Point(this.Width-40,0),
new Point(this.Width-1,this.Height/2),
new Point(this.Width-40,this.Height),
new Point(this.Width-40,this.Height-this.Height/4),
new Point(40,this.Height-this.Height/4),
new Point(40,this.Height),
new Point(0,this.Height/2),
};
break;
case ArrowDirection.Top_Bottom:
ps = new Point[]
{
new Point(this.Width/2,0),
new Point(this.Width,40),
new Point(this.Width-this.Width/4,40),
new Point(this.Width-this.Width/4,this.Height-40),
new Point(this.Width,this.Height-40),
new Point(this.Width/2,this.Height-1),
new Point(0,this.Height-40),
new Point(this.Width/4,this.Height-40),
new Point(this.Width/4,40),
new Point(0,40),
new Point(this.Width/2,0),
};
break;
}
m_path = new GraphicsPath();
m_path.AddLines(ps);
m_path.CloseAllFigures();
}
/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SetGDIHigh();
g.FillPath(new SolidBrush(arrowColor), m_path);
if (borderColor != null && borderColor != Color.Empty)
g.DrawPath(new Pen(new SolidBrush(borderColor.Value)), m_path);
if (!string.IsNullOrEmpty(text))
{
var size = g.MeasureString(Text, Font);
g.DrawString(Text, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / 2, (this.Height - size.Height) / 2));
}
}
}
/// <summary>
/// Enum ArrowDirection
/// </summary>
public enum ArrowDirection
{
/// <summary>
/// The left
/// </summary>
Left,
/// <summary>
/// The right
/// </summary>
Right,
/// <summary>
/// The top
/// </summary>
Top,
/// <summary>
/// The bottom
/// </summary>
Bottom,
/// <summary>
/// The left right
/// </summary>
Left_Right,
/// <summary>
/// The top bottom
/// </summary>
Top_Bottom
}
}
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧