一、前言

技术没有先进与落后,只有合适与不合适。

本篇的自定义控件是:开关按钮(SwitchButton)。

开关按钮非常简单,实现方式也多种多样,比如常见的:使用两张不同的按钮图片,代表开和关,然后在点击时切换这两张图片。

而本篇和前两篇一脉相承,都是继承Control,使用GDI+去实现。因为都是相同的原理,所以如果看过前两篇的讲解,自己就可以实现出来。

虽说简单,但仍有可雕琢之处,在基本的实现外,我还会加入缓动效果,以达到更加自然的动画效果。

关于缓动,可以查看这两篇文章:

《三角函数与缓入缓出动画及C#实现(图文讲解)》

《缓动公式整理(附:C#实现及WPF原版对比)》

相信看完的你,一定会有所收获。

本文地址:https://www.cnblogs.com/lesliexin/p/13552662.html


二、前期分析

(一)为什么需要开关按钮?

“开关按钮(SwitchButton)”虽然不常听说,但是到处都可以见到它的身影,手机、电脑、网页等等到处都有“开关按钮”。

“开关按钮”的基本样式如下:

“开关按钮”效果很直观,使用也很方便,但是在WinForm中却没有提供该控件,所以便需要自己去实现“开关按钮”。

(二)实现目标

1,外观

基本外观如下:

同时可以配合Label控件来进行提示:

2,功能和特点

(1)支持动画效果

不是简单的“开”、“关”两个状态生硬的切换,而是需要有相应的动画效果,包括按钮圆点位置的变化、颜色的变化。

同时为了使圆点的移动更加自然,需要使用缓动效果。

(2)支持修改颜色

可以修改“关”时的背景条颜色、“开”时的背景条颜色、按钮圆点的颜色。

(3)支持修改按钮圆点的大小和背景条的大小

比如将按钮圆点调小一点,便可以实现类似Win10中开关按钮的效果:

比如将背景条调细,便可以实现很特别的效果:

(三)技术分析

仍是使用GDI+去实现,其原理上就是在简化版的LTrackBar上加一个圆点。

而动画效果,就是改变圆点的位置和前景条的宽度。关于动画效果的的实现原理可以参考《三角函数与缓入缓出动画及C#实现(图文讲解)》


三、开始实现

(一)前期准备。

此处仅作提纲,具体操作见前篇。

新建类:LScrollBar.cs

添加继承:Control(需要添加引用:System.Windows.Forms.dll)

修改可访问性为:public

(二)添加属性

1,”开“状态时背景条颜色

此颜色是当开关按钮代表”开“的时候背景条的颜色。

2,”关“状态时背景条颜色

此颜色是当开关按钮代表”关“的时候背景条的颜色。

3,按钮圆点颜色

此颜色是按钮圆点的颜色

4,背景条高度

背景条的高度即可以高于按钮圆点,也可以低于按钮圆点。

5,按钮圆点高度

按钮圆点高度(直径)即可以高于背景条高度,也可以低于背景条高度。

因为“背景条高度”和“按钮圆点高度”不一定谁高谁低,所以为了方便使用,将自动调整控件尺寸为两者较高的一方。

6,圆点距左右两侧距离

当“背景条高度”大于“按钮圆点高度”时,为了使按钮圆点边缘距背景条边缘距离相等,所以需要通过此属于去设置。

比如:背景条高度为24,圆点高度为20,那么将本属性设置为(24-20)/2=2,即可达到圆点边缘距背景条边缘距离相等。

7,”开“、”关“状态

此状态用于标识或设置开关按钮的开关状态。

(三)添加事件

对于开关按钮而言,只需要一个事件,那就是开关状态发生改变时所产生的事件。

其中事件数据如下:

(四)重写方法

1,OnPaint

在本方法中,我们要画三个:背景条、前景条、圆点。

2,OnMouseDown

本方法代表鼠标点击了开关按钮。在此方法中,我们要实现以下操作:改变开关状态、启动动画效果。

而动画效果的实现,是使用定时器,不断改变位置,并发生重绘。

在动画效果结束后,停止定时器,并触发开关状态改变事件:LSwitched。之所以在此处触发事件而不是在OnMouseDown中触发,是为了避免事件LSwitched的实现阻塞动画效果的实现。

在定时器事件中,使用了《缓动公式整理(附:C#实现及WPF原版对比)》中所编译的DLL,其调用的方法源代码如下,不想引用该DLL可以直接使用下方代码代替。

(五)添加双缓冲

为了避免重绘时闪烁,可在其构造函数中加上对双缓冲的支持。

(六)添加默认事件

为了实现双击控件就自动实现仅有的一个事件,故添加默认事件。


四、效果演示

在Form上添加本控件:LSwitchButton,调整控件各个属性,并在旁边添加一Label。

双击本控件,在事件中输入以下代码:

运行程序,即可见到以下效果:


五、调整优化

就像本文开篇所说那样:虽然简单,但仍可雕琢。在这里,将会对开关控件进行调整和优化。

(一)圆点切边优化

虽然乍看起来没什么问题,但是在某些情况下,会发现按钮圆点下方会被切去一点。如下:

虽然实现逻辑上是没有问题的,但是实际效果确有此偏差,所以在这里我们需要手动去调整,将控件的高度多添加一个像素,这样就可以解决切边问题了。

(二)多种缓动效果支持

即然在本例中已经引用了缓动DLL(见:《缓动公式整理(附:C#实现及WPF原版对比)》),那么不妨使开关按钮的动画支持所有缓动效果。

1,添加缓动效果属性

2,修改定时器事件,添加所有缓动效果支持

3,不同缓动效果开关按钮演示

注:由于GIF录制帧率的限制,下方的缓动演示效果比实际效果要差上很多。

(1),默认(Quartic)

(2),Back

(3),Bounce


六、结束语

本篇并没有什么复杂难懂的知识,更多的是对已掌握知识的运用,特别是对前篇《缓动公式整理(附:C#实现及WPF原版对比)》中的缓动效果的使用。

技术并没有先进和落后,只有合适与不合适。

所以,对自己掌握的知识多抱有一些信心,尽情释放自己的想像力,并在实践中提升自己。


七、源代码及工程下载

https://files.cnblogs.com/files/lesliexin/03,LSwitchButton.7z

[C#] (原创)一步一步教你自定义控件——03,SwitchButton(开关按钮)的更多相关文章

  1. [C#] (原创)一步一步教你自定义控件——01,TrackBar

    一.前言 技术没有先进落后之分,只有合不合适. WinForm有着非常多的优点,在使用WinForm久了之后,难免会觉得WinForm自带的某些控件外观上有些许朴素.或者功能上有些不如意,自然而然便想 ...

  2. [C#] (原创)一步一步教你自定义控件——04,ProgressBar(进度条)

    一.前言 技术没有先进与落后,只有合适与不合适. 本篇的自定义控件是:进度条(ProgressBar). 进度条的实现方式多种多样,主流的方式有:使用多张图片去实现.使用1个或2个Panel放到Use ...

  3. Ace教你一步一步做Android新闻客户端(一)

    复制粘贴了那么多博文很不好意思没点自己原创的也说不出去,现在写一篇一步一步教你做安卓新闻客户端,借此机会也是让自己把相关的技术再复习一遍,大神莫笑,专门做给新手看. 手里存了两篇,一个包括软件视图 和 ...

  4. 一步一步教你如何在linux下配置apache+tomcat(转)

    一步一步教你如何在linux下配置apache+tomcat   一.安装前准备. 1.   所有组件都安装到/usr/local/e789目录下 2.   解压缩命令:tar —vxzf 文件名(. ...

  5. 一步一步教你将普通的wifi路由器变为智能广告路由器

    一步一步教你将普通的wifi路由器变为智能广告路由器 相信大家对WiFi智能广告路由器已经不再陌生了,现在很多公共WiFi上网,都需要登录并且验证,这也就是WiFi广告路由器的最重要的功能.大致就是下 ...

  6. 一步一步教你使用Git

    一步一步教你使用Git 互联网给我们带来方便的同时,也时常让我们感到困惑.随便搜搜就出一大堆结果,然而总是有大量的重复和错误.小妖发出的内容,都是自己实测过的,有问题请留言. 现在,你已经安装了Git ...

  7. 微凉大大,教你一步一步在linux中正确的安装Xcache加速php。

    首先,强烈吐槽,百度上的教程,都左复制右复制的,乱七八糟,缺东缺西的.借此微凉大大我提供我苦心整理好的教程.以便各位小菜能顺利的使用Xcache加速php,假设看完了,也操作了,还是失败了的话,请联系 ...

  8. 使用WPF教你一步一步实现连连看

    使用WPF教你一步一步实现连连看(一) 第一步: 问题,怎样动态的建立一个10*10的grid(布局) for (int i = 0; i < 10; i++){ RowDefinition r ...

  9. (原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂

    (原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂 1. 在官网https://struts.apache.org下载Struts2,建议下载2.3系列版本.从图中可以看出 ...

随机推荐

  1. Git+Gitlab+Ansible的roles实现一键部署Nginx静态网站(4)

    前言 截止目前已经写了<Ansible基础认识及安装使用详解(一)–技术流ken>,<Ansible常用模块介绍及使用(二)–技术流ken><Ansible剧本介绍及使用 ...

  2. Spring系列之新注解配置+Spring集成junit+注解注入

    Spring系列之注解配置 Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率 你本来要写一段很长的代码来构造一个 ...

  3. pandas 使用技巧

    多列展示 查看DataFrame时,列数较多会省略中间列的信息,可以设置最大展示列数,代码如下: 1 import pandas as pd 2 pd.set_option('display.max_ ...

  4. JavaScript的this到底代表谁?(this指向哪里?)

    在很多编程语言中都有this这个特殊关键字的存在,比如Java中的this,还有本文要说到的JavaScript中的this.那么,JavaScript中this究竟有什么特性和用法呢?它又是如何定义 ...

  5. Linux里面的压缩和解压类指令

    gzip/gunzip 指令 ( .gz  不能压缩目录) gzip 用于压缩文件, gunzip 用于解压的 . gzip gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后 ...

  6. 快速删除XMind指定层级的方法

    在使用xmind梳理知识点的时候,因为长期积累,单个文件的节点数可能超过1000个,层级可能超过6层.但在我们做文件分享时,可能只需要提供3层的思维导图,这时候就需要对子节点进行删除.原始的方法,就是 ...

  7. Hibernate4.3 QBC查询

    一.基本查询 1 Session session = HibernateUtils.getSession(); 2 //创建QBC查询接口的实现类 3 Criteria criteria = sess ...

  8. 使用 Aria2 代替迅雷

    一.原因 迅雷下载速度一般,thunder:// 开头的链接也逐渐被 bt 链接替代. 迅雷很流氓,安装后 (尤其是 Windows 系统) 浏览器默认使用迅雷下载,对于小文件来说使用浏览器内置下载可 ...

  9. ReverseFind的用法 ; 查找字符中最后一个字符

    转载:https://blog.csdn.net/frivolousinstant/article/details/52796922 ReverseFind CString::ReverseFind ...

  10. sql注入里关键字绕过的发现

    网上大量文章,甚至<黑客攻防技术实战宝典-WEB实战篇>里面都说一些关键字如 select 等绕过可以用注释符/**/. 例如: select,union.可以用 ,se/**/lect, ...