前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
官网:https://www.hzhcontrols.cn
GitHub:https://github.com/kwwwvagaa/NetWinformControl
如果觉得写的还行,请点个 star 支持一下吧
目录
c#Winform自定义控件-目录_c#winform自定义控件-有图标的按钮-CSDN博客
准备工作
GDI+需要有一点了解,不知道的可以百度瞅瞅
开始
添加一个用户控件,命名UCSwitch
添加一个枚举用以控制样式
1 public enum SwitchType
2 {
3 /// <summary>
4 /// 椭圆
5 /// </summary>
6 Ellipse,
7 /// <summary>
8 /// 四边形
9 /// </summary>
10 Quadrilateral,
11 /// <summary>
12 /// 横线
13 /// </summary>
14 Line
15 }
添加属性
1 [Description("选中改变事件"), Category("自定义")]
2 public event EventHandler CheckedChanged;
3 private Color m_trueColor = Color.FromArgb(34, 163, 169);
4
5 [Description("选中时颜色"), Category("自定义")]
6 public Color TrueColor
7 {
8 get { return m_trueColor; }
9 set
10 {
11 m_trueColor = value;
12 Refresh();
13 }
14 }
15
16 private Color m_falseColor = Color.FromArgb(111, 122, 126);
17
18 [Description("没有选中时颜色"), Category("自定义")]
19 public Color FalseColor
20 {
21 get { return m_falseColor; }
22 set
23 {
24 m_falseColor = value;
25 Refresh();
26 }
27 }
28
29 private bool m_checked;
30
31 [Description("是否选中"), Category("自定义")]
32 public bool Checked
33 {
34 get { return m_checked; }
35 set
36 {
37 m_checked = value;
38 Refresh();
39 if (CheckedChanged != null)
40 {
41 CheckedChanged(this, null);
42 }
43 }
44 }
45
46 private string[] m_texts;
47
48 [Description("文本值,当选中或没有选中时显示,必须是长度为2的数组"), Category("自定义")]
49 public string[] Texts
50 {
51 get { return m_texts; }
52 set
53 {
54 m_texts = value;
55 Refresh();
56 }
57 }
58 private SwitchType m_switchType = SwitchType.Ellipse;
59
60 [Description("显示类型"), Category("自定义")]
61 public SwitchType SwitchType
62 {
63 get { return m_switchType; }
64 set
65 {
66 m_switchType = value;
67 Refresh();
68 }
69 }
70
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 }
重绘
1 protected override void OnPaint(PaintEventArgs e)
2 {
3 base.OnPaint(e);
4 var g = e.Graphics;
5 g.SetGDIHigh();
6 if (m_switchType == HZH_Controls.Controls.SwitchType.Ellipse)
7 {
8 var fillColor = m_checked ? m_trueColor : m_falseColor;
9 GraphicsPath path = new GraphicsPath();
10 path.AddLine(new Point(this.Height / 2, 1), new Point(this.Width - this.Height / 2, 1));
11 path.AddArc(new Rectangle(this.Width - this.Height - 1, 1, this.Height - 2, this.Height - 2), -90, 180);
12 path.AddLine(new Point(this.Width - this.Height / 2, this.Height - 1), new Point(this.Height / 2, this.Height - 1));
13 path.AddArc(new Rectangle(1, 1, this.Height - 2, this.Height - 2), 90, 180);
14 g.FillPath(new SolidBrush(fillColor), path);
15
16 string strText = string.Empty;
17 if (m_texts != null && m_texts.Length == 2)
18 {
19 if (m_checked)
20 {
21 strText = m_texts[0];
22 }
23 else
24 {
25 strText = m_texts[1];
26 }
27 }
28
29 if (m_checked)
30 {
31 g.FillEllipse(Brushes.White, new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
32 if (string.IsNullOrEmpty(strText))
33 {
34 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
35 }
36 else
37 {
38 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
39 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
40 g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY));
41 }
42 }
43 else
44 {
45 g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
46 if (string.IsNullOrEmpty(strText))
47 {
48 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
49 }
50 else
51 {
52 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
53 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
54 g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
55 }
56 }
57 }
58 else if (m_switchType == HZH_Controls.Controls.SwitchType.Quadrilateral)
59 {
60 var fillColor = m_checked ? m_trueColor : m_falseColor;
61 GraphicsPath path = new GraphicsPath();
62 int intRadius = 5;
63 path.AddArc(0, 0, intRadius, intRadius, 180f, 90f);
64 path.AddArc(this.Width - intRadius - 1, 0, intRadius, intRadius, 270f, 90f);
65 path.AddArc(this.Width - intRadius - 1, this.Height - intRadius - 1, intRadius, intRadius, 0f, 90f);
66 path.AddArc(0, this.Height - intRadius - 1, intRadius, intRadius, 90f, 90f);
67
68 g.FillPath(new SolidBrush(fillColor), path);
69
70 string strText = string.Empty;
71 if (m_texts != null && m_texts.Length == 2)
72 {
73 if (m_checked)
74 {
75 strText = m_texts[0];
76 }
77 else
78 {
79 strText = m_texts[1];
80 }
81 }
82
83 if (m_checked)
84 {
85 GraphicsPath path2 = new GraphicsPath();
86 path2.AddArc(this.Width - this.Height - 1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f);
87 path2.AddArc(this.Width - 1 - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f);
88 path2.AddArc(this.Width - 1 - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f);
89 path2.AddArc(this.Width - this.Height - 1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f);
90 g.FillPath(Brushes.White, path2);
91
92 if (string.IsNullOrEmpty(strText))
93 {
94 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
95 }
96 else
97 {
98 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
99 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
100 g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY));
101 }
102 }
103 else
104 {
105 GraphicsPath path2 = new GraphicsPath();
106 path2.AddArc(1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f);
107 path2.AddArc(this.Height - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f);
108 path2.AddArc(this.Height - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f);
109 path2.AddArc(1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f);
110 g.FillPath(Brushes.White, path2);
111
112 //g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
113 if (string.IsNullOrEmpty(strText))
114 {
115 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
116 }
117 else
118 {
119 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
120 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
121 g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
122 }
123 }
124 }
125 else
126 {
127 var fillColor = m_checked ? m_trueColor : m_falseColor;
128 int intLineHeight = (this.Height - 2 - 4) / 2;
129
130 GraphicsPath path = new GraphicsPath();
131 path.AddLine(new Point(this.Height / 2, (this.Height - intLineHeight) / 2), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2));
132 path.AddArc(new Rectangle(this.Width - this.Height / 2 - intLineHeight - 1, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), -90, 180);
133 path.AddLine(new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight));
134 path.AddArc(new Rectangle(this.Height / 2, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), 90, 180);
135 g.FillPath(new SolidBrush(fillColor), path);
136
137 if (m_checked)
138 {
139 g.FillEllipse(new SolidBrush(fillColor), new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
140 g.FillEllipse(Brushes.White, new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
141 }
142 else
143 {
144 g.FillEllipse(new SolidBrush(fillColor), new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
145 g.FillEllipse(Brushes.White, new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 + 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
146 }
147 }
148 }
处理一下点击事件
1 void UCSwitch_MouseDown(object sender, MouseEventArgs e)
2 {
3 Checked = !Checked;
4 }
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace HZH_Controls.Controls
{
[DefaultEvent("CheckedChanged")]
public partial class UCSwitch : UserControl
{
[Description("选中改变事件"), Category("自定义")]
public event EventHandler CheckedChanged;
private Color m_trueColor = Color.FromArgb(34, 163, 169);
[Description("选中时颜色"), Category("自定义")]
public Color TrueColor
{
get { return m_trueColor; }
set
{
m_trueColor = value;
Refresh();
}
}
private Color m_falseColor = Color.FromArgb(111, 122, 126);
[Description("没有选中时颜色"), Category("自定义")]
public Color FalseColor
{
get { return m_falseColor; }
set
{
m_falseColor = value;
Refresh();
}
}
private bool m_checked;
[Description("是否选中"), Category("自定义")]
public bool Checked
{
get { return m_checked; }
set
{
m_checked = value;
Refresh();
if (CheckedChanged != null)
{
CheckedChanged(this, null);
}
}
}
private string[] m_texts;
[Description("文本值,当选中或没有选中时显示,必须是长度为2的数组"), Category("自定义")]
public string[] Texts
{
get { return m_texts; }
set
{
m_texts = value;
Refresh();
}
}
private SwitchType m_switchType = SwitchType.Ellipse;
[Description("显示类型"), Category("自定义")]
public SwitchType SwitchType
{
get { return m_switchType; }
set
{
m_switchType = value;
Refresh();
}
}
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
Refresh();
}
}
public UCSwitch()
{
InitializeComponent();
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.MouseDown += UCSwitch_MouseDown;
}
void UCSwitch_MouseDown(object sender, MouseEventArgs e)
{
Checked = !Checked;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SetGDIHigh();
if (m_switchType == HZH_Controls.Controls.SwitchType.Ellipse)
{
var fillColor = m_checked ? m_trueColor : m_falseColor;
GraphicsPath path = new GraphicsPath();
path.AddLine(new Point(this.Height / 2, 1), new Point(this.Width - this.Height / 2, 1));
path.AddArc(new Rectangle(this.Width - this.Height - 1, 1, this.Height - 2, this.Height - 2), -90, 180);
path.AddLine(new Point(this.Width - this.Height / 2, this.Height - 1), new Point(this.Height / 2, this.Height - 1));
path.AddArc(new Rectangle(1, 1, this.Height - 2, this.Height - 2), 90, 180);
g.FillPath(new SolidBrush(fillColor), path);
string strText = string.Empty;
if (m_texts != null && m_texts.Length == 2)
{
if (m_checked)
{
strText = m_texts[0];
}
else
{
strText = m_texts[1];
}
}
if (m_checked)
{
g.FillEllipse(Brushes.White, new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
if (string.IsNullOrEmpty(strText))
{
g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
else
{
System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY));
}
}
else
{
g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
if (string.IsNullOrEmpty(strText))
{
g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
else
{
System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
}
}
}
else if (m_switchType == HZH_Controls.Controls.SwitchType.Quadrilateral)
{
var fillColor = m_checked ? m_trueColor : m_falseColor;
GraphicsPath path = new GraphicsPath();
int intRadius = 5;
path.AddArc(0, 0, intRadius, intRadius, 180f, 90f);
path.AddArc(this.Width - intRadius - 1, 0, intRadius, intRadius, 270f, 90f);
path.AddArc(this.Width - intRadius - 1, this.Height - intRadius - 1, intRadius, intRadius, 0f, 90f);
path.AddArc(0, this.Height - intRadius - 1, intRadius, intRadius, 90f, 90f);
g.FillPath(new SolidBrush(fillColor), path);
string strText = string.Empty;
if (m_texts != null && m_texts.Length == 2)
{
if (m_checked)
{
strText = m_texts[0];
}
else
{
strText = m_texts[1];
}
}
if (m_checked)
{
GraphicsPath path2 = new GraphicsPath();
path2.AddArc(this.Width - this.Height - 1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f);
path2.AddArc(this.Width - 1 - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f);
path2.AddArc(this.Width - 1 - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f);
path2.AddArc(this.Width - this.Height - 1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f);
g.FillPath(Brushes.White, path2);
if (string.IsNullOrEmpty(strText))
{
g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
else
{
System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY));
}
}
else
{
GraphicsPath path2 = new GraphicsPath();
path2.AddArc(1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f);
path2.AddArc(this.Height - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f);
path2.AddArc(this.Height - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f);
path2.AddArc(1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f);
g.FillPath(Brushes.White, path2);
//g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
if (string.IsNullOrEmpty(strText))
{
g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
else
{
System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
}
}
}
else
{
var fillColor = m_checked ? m_trueColor : m_falseColor;
int intLineHeight = (this.Height - 2 - 4) / 2;
GraphicsPath path = new GraphicsPath();
path.AddLine(new Point(this.Height / 2, (this.Height - intLineHeight) / 2), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2));
path.AddArc(new Rectangle(this.Width - this.Height / 2 - intLineHeight - 1, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), -90, 180);
path.AddLine(new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight));
path.AddArc(new Rectangle(this.Height / 2, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), 90, 180);
g.FillPath(new SolidBrush(fillColor), path);
if (m_checked)
{
g.FillEllipse(new SolidBrush(fillColor), new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
g.FillEllipse(Brushes.White, new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
else
{
g.FillEllipse(new SolidBrush(fillColor), new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4));
g.FillEllipse(Brushes.White, new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 + 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2));
}
}
}
}
public enum SwitchType
{
/// <summary>
/// 椭圆
/// </summary>
Ellipse,
/// <summary>
/// 四边形
/// </summary>
Quadrilateral,
/// <summary>
/// 横线
/// </summary>
Line
}
}
namespace HZH_Controls.Controls
{
partial class UCSwitch
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// UCSwitch
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.Transparent;
this.Name = "UCSwitch";
this.Size = new System.Drawing.Size(83, 31);
this.ResumeLayout(false);
}
#endregion
}
}