目录
前言
C#Form窗体中自带的选择按钮控件外观单一,已不适合现在的窗体设计,所以我们需要自定义制作一个选择按钮控件,这个选择按钮有三种形态分别为椭圆,矩形,线性,如图所示:
一、创建一个自定义控件项目
在VS中新建项目,选择Windows窗体控件库,并创建,如下图所示:
设计窗口如下图所示:
二、关键技术
1.添加控件属性
添加控件控件属性,“选择时改变事件”,"是否选中","当选中true时显示的文本","当选中flase时显示的文本","选择为true时的颜色","选择为flase时的颜色","选择为true时的文本颜色","选择为flase时的文本颜色","开关的外框显示类型","显示文本的字体",代码如下:
[Description("选择时改变事件"), Category("自定义")]
public event EventHandler CheckedChanged;
private bool myChecked;
[Description("是否选中"), Category("自定义")]
public bool Checked
{
get { return myChecked; }
set
{
myChecked = value;
Refresh();
if (CheckedChanged != null)
{
CheckedChanged(this, null);
}
}
}
private string myTrueText;
[Description("当选中true时显示的文本"), Category("自定义")]
public string TrueText
{
get { return myTrueText; }
set
{
myTrueText = value;
Refresh();
}
}
private string myFlaseText;
[Description("当选中flase时显示的文本"), Category("自定义")]
public string FlaseText
{
get { return myFlaseText; }
set
{
myFlaseText = value;
Refresh();
}
}
[Description("选择为true时的颜色"), Category("自定义")]
private Color myCheckedTrueColor = Color.Green;
public Color CheckedTrueColor
{
get { return myCheckedTrueColor; }
set
{
myCheckedTrueColor = value;
Refresh();
}
}
[Description("选择为flase时的颜色"), Category("自定义")]
private Color myCheckedFlaseColor = Color.Gray;
public Color CheckedFlaseColor
{
get { return myCheckedFlaseColor; }
set
{
myCheckedFlaseColor = value;
Refresh();
}
}
[Description("选择为true时的文本颜色"), Category("自定义")]
private Color myCheckedTrueTextColor = Color.Blue;
public Color CheckedTrueTextColor
{
get { return myCheckedTrueTextColor; }
set
{
myCheckedTrueTextColor = value;
Refresh();
}
}
[Description("选择为flase时的文本颜色"), Category("自定义")]
private Color myCheckedFlaseTextColor = Color.Black;
public Color CheckedFlaseTextColor
{
get { return myCheckedFlaseTextColor; }
set
{
myCheckedFlaseTextColor = value;
Refresh();
}
}
private SwitchType mySwitchType = SwitchType.Ellipse;
[Description("开关的外框显示类型"), Category("自定义")]
public SwitchType SwitchType
{
get { return mySwitchType; }
set
{
mySwitchType = value;
Refresh();
}
}
[Description("显示文本的字体"), Category("自定义")]
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
Refresh();
}
}
2.控件初始化
需要添加鼠标按下事件,代码如下:
public UserControl1()
{
InitializeComponent();
this.MouseDown += Switch_MouseDown;
}
void Switch_MouseDown(object sender, MouseEventArgs e)
{
Checked = !Checked;
}
3.开关按钮的类型
需要写一个开关按钮显示类型的枚举,代码如下:
/// <summary>
/// Enum SwitchType
/// </summary>
public enum SwitchType
{
/// <summary>
/// 椭圆
/// </summary>
Ellipse,
/// <summary>
/// 四边形
/// </summary>
Quadrilateral,
/// <summary>
/// 横线
/// </summary>
Line
}
4.重绘事件
需要重写绘制事件,代码如下:
/// <summary>
/// 重写绘制事件
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
Color color;
if (myChecked)
{
color = myCheckedTrueColor;
}
else
{
color = myCheckedFlaseColor;
}
if (mySwitchType == SwitchType.Ellipse)
{
GraphicsPath path = new GraphicsPath();
path.AddArc(new Rectangle(this.Width - this.Height - 1, 1, this.Height - 2, this.Height - 2), -90, 180);
path.AddArc(new Rectangle(1, 1, this.Height - 2, this.Height - 2), 90, 180);
g.FillPath(new SolidBrush(color), path);
if (myChecked)
{
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(myTrueText))
{
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(myTrueText, Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(myTrueText, Font, new SolidBrush(myCheckedTrueTextColor), 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(myFlaseText))
{
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(myFlaseText, Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(myFlaseText, Font, new SolidBrush(myCheckedFlaseTextColor), new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
}
}
}
else if (mySwitchType == SwitchType.Quadrilateral)
{
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(color), path);
if (myChecked)
{
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(myTrueText))
{
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(myTrueText, Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(myTrueText, Font, new SolidBrush(myCheckedTrueTextColor), 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(myFlaseText))
{
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(myFlaseText, Font);
int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2;
g.DrawString(myFlaseText, Font, new SolidBrush(myCheckedFlaseTextColor), new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY));
}
}
}
else if (mySwitchType == SwitchType.Line)
{
int intLineHeight = (this.Height - 2 - 4) / 2;
GraphicsPath path = new GraphicsPath();
path.AddArc(new Rectangle(this.Width - this.Height / 2 - intLineHeight - 1, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), -90, 180);//右圆弧
path.AddArc(new Rectangle(this.Height / 2, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), 90, 180);
g.FillPath(new SolidBrush(color), path);//左圆弧
if (myChecked)
{
g.FillEllipse(new SolidBrush(color), 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(color), 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));
}
}
}
5.效果展示
实际效果展示如下:
三、总结
这样我就用C#做了一个开关式的选择按钮,拥有三种样式,可以各区域的颜色,可以添加要显示的文字,可以更改文字的字体,颜色等。