原创C#Winform桌面应用中实用又美观的开关控件源码分享

在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” ,只要稍作修改就可以改变控件的含义,例如 “是/否”、“打开/关闭”、“有效/无效”等等。
若感兴趣可下载完整源码。
下载源码

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyq106

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值