在C#Winform开发中,通常将checkbox当做开关控件,但是是不是觉得很丑呢?这里给大家分享一个我自己原创的winform开关控件,先上个图吧。
怎么样,用这个代替checkbox,你的程序应该会瞬间上一个档次。
直接进入代码吧。
首先,创建一个类,这个类就是开关控件类。取名UC_Switch,继承PictureBox(因为它本质上就是一个图片元素)。
/// <summary>
/// 开关控件
/// author:hyq
/// e-mail:huangyq1984@qq.com
/// </summary>
public partial class UC_Switch : PictureBox
{
public UC_Switch() : base()
{
this.Height = 25; this.Width = 80;
this.BackColor = Color.Transparent;
//设置默认关闭状态
SetState(0, false);
//点击事件
this.Click += new EventHandler((sender, e) =>
{
//判断是否允许修改状态
bool canChange = true;
if (allowChangeState != null)
canChange = allowChangeState();
//如果允许修改,则修改当前状态
if (canChange)
{
SetState(curState == 0?1:0, true);
}
});
}
/// <summary>
/// 当前状态,默认关闭
/// </summary>
private int curState = 0;
/// <summary>
/// 判断是否允许修改状态,由外部去实现(可实现也可不实现,不实现时默认允许修改)
/// </summary>
public Func<bool> allowChangeState { get; set; }
/// <summary>
/// 状态发生变化时的回调Action
/// </summary>
public Action stateChanged { get; set; }
/// <summary>
/// 是否是打开状态
/// </summary>
public bool Opened { get { return curState == 1; } }
/// <summary>
/// 打开开关,不触发事件
/// </summary>
public void Open()
{
SetState(1, false);
}
/// <summary>
/// 关闭开关,不触发事件
/// </summary>
public void Close()
{
SetState(0, false);
}
/// <summary>
/// 设置开关状态,并选择是否触发事件
/// </summary>
/// <param name="state">0-关闭,1-开启</param>
/// <param name="trrigerChangedEvent">是否触发事件</param>
public void SetState(int state, bool trrigerChangedEvent)
{
Image img = PaintSwitchImage(state);
this.Image = GetImageToFitPictureBox(this, img, "", Color.Transparent);
curState = state;
if (trrigerChangedEvent)
{
stateChanged?.Invoke();
}
}
}
上面代码中的PaintSwitchImage方法,是根据开关状态绘制图片,GetImageToFitPictureBox方法,是根据PictureBox的尺寸调整图片大小,但不改变图片长宽比例。因为代码篇幅较长,这里没有把这两个方法贴出来,下面只讲解一下思路及部分代码。
PaintSwitchImage要用到GDI绘图,主要用到Bitmap、Graphics、Pen、Brush、Rectangle等类。首先创建一个Bitmap、Graphics对象,注意设置Graphics属性。
//封装一个 GDI+ 绘图图面
Graphics g = Graphics.FromImage(bm);
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
仔细观察开关控件的图片,我们可以把开关控件分为左中右3个部分,左右两边是一个圆形,中间是一个长方形,两个圆形的一半都叠加在长方形中,这样可以使用Pen画出部分叠加的左右两个圆及中间的长方形。
//画笔,左右两个圆圈及中间一个长方形
Pen p = new Pen(Color.LightGray);
g.DrawEllipse(p, new Rectangle(0, 0, 30, 30));
g.DrawEllipse(p, new Rectangle(50, 0, 30, 30));
g.DrawRectangle(p, new Rectangle(15, 0, 50, 30));
然后用画刷Brush(为了美观,我们使用线性渐变画刷LinearGradientBrush),根据当前开关状态state,填充图形内部颜色。
最后,还要填写 on 或 off 字样,并且在旁边画出一个小圆,这里我们用SolidBrush。注意,开关状态不同,字符和小圆的位置及颜色都不同。
//填写字符,on/off
Brush b = new SolidBrush(state == 0 ? Color.Gray : Color.White);
System.Drawing.Font f = new System.Drawing.Font("微软雅黑", 12, FontStyle.Regular);
if (state == 0)
{
g.FillEllipse(b, new Rectangle(3, 3, 24, 24));
g.DrawString("OFF", f, b, 32, 5);
}
else
{
g.FillEllipse(b, new Rectangle(51, 3, 24, 24));
g.DrawString("ON", f, b, 12, 5);
}
另外,GetImageToFitPictureBox方法,只是在不改变长宽比例的前提下根据PictureBox的尺寸调整图片大小,主要考验小学数学知识,代码就不贴出来了。
除了显示 “on/off” ,只要稍作修改就可以改变控件的含义,例如 “是/否”、“打开/关闭”、“有效/无效”等等。
若感兴趣可下载完整源码。
下载源码