winform桌面软件开发,在工业控制领域的使用还是很广泛的,打算好好学习一下GDI+绘图。以前都是用别人的轮子,自己也打算封装一些工业控制领域常用的控件。

今天要将的是,利用缓动函数动态绘制电池。

首先在网上搜索了一些常用的缓动函数,并用Animation类做了二次封装。(引用自:http://dsqiu.iteye.com ,感谢)

    public enum AnimationType
{
Linear,
EaseIn,
EaseOut,
EaseInOut,
BounceIn,
BounceOut,
QuadEaseOut,
QuadEaseIn,
QuadEaseInOut,
QuadEaseOutIn, //新增40种动画效果
ExpoEaseOut,
ExpoEaseIn,
ExpoEaseInOut,
ExpoEaseOutIn,
CubicEaseOut,
CubicEaseIn,
CubicEaseInOut,
CubicEaseOutIn,
QuartEaseOut,
QuartEaseIn,
QuartEaseInOut,
QuartEaseOutIn,
QuintEaseOut,
QuintEaseIn,
QuintEaseInOut,
QuintEaseOutIn,
CircEaseOut,
CircEaseIn,
CircEaseInOut,
CircEaseOutIn,
SineEaseOut,
SineEaseIn,
SineEaseInOut,
SineEaseOutIn,
ElasticEaseOut,
ElasticEaseIn,
ElasticEaseInOut,
ElasticEaseOutIn,
BounceEaseOut,
BounceEaseIn,
BounceEaseInOut,
BounceEaseOutIn,
BackEaseOut,
BackEaseIn,
BackEaseInOut,
BackEaseOutIn
}

自己二次封装Animation的类,对外公开一个缓动函数值改变的事件,以及动画开始、结束的方法。

封装的逻辑是,调用AnimationStart方法后,会在线程池中加入一个定时生产缓动函数对应值的方法,通过调用对外公开的事件。

外部不停调用AnimationStart方法时,会自动扔弃上一次未完成的定时生产缓动函数值的任务。

public class Animation
{
private AnimationType animationType = AnimationType.EaseInOut;
/// <summary>
/// 设置动画类型
/// </summary>
public AnimationType AnimationType { get => animationType; set => animationType = value; }
/// <summary>
/// 设置动画持续时间
/// </summary>
public int Duration
{
get => duration;
set => duration = value;
} private int duration = 200; private int span = 10; private int version = 0; public event EventHandler<AnimationEventArgs> AnimationComing; public float GetEaseProgress(AnimationType ease_type, float linear_progress)
{
switch (ease_type)
{
case AnimationType.Linear:
return linear_progress;
case AnimationType.BackEaseIn:
return AnimationMethod.BackEaseIn(linear_progress, 0, 1, duration);
case AnimationType.BackEaseInOut:
return AnimationMethod.BackEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.BackEaseOut:
return AnimationMethod.BackEaseOut(linear_progress, 0, 1, duration);
case AnimationType.BackEaseOutIn:
return AnimationMethod.BackEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseIn:
return AnimationMethod.BounceEaseIn(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseInOut:
return AnimationMethod.BounceEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseOut:
return AnimationMethod.BounceEaseOut(linear_progress, 0, 1, duration);
case AnimationType.BounceEaseOutIn:
return AnimationMethod.BounceEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.CircEaseIn:
return AnimationMethod.CircEaseIn(linear_progress, 0, 1, duration);
case AnimationType.CircEaseInOut:
return AnimationMethod.CircEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.CircEaseOut:
return AnimationMethod.CircEaseOut(linear_progress, 0, 1, duration);
case AnimationType.CircEaseOutIn:
return AnimationMethod.CircEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseIn:
return AnimationMethod.CubicEaseIn(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseInOut:
return AnimationMethod.CubicEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseOut:
return AnimationMethod.CubicEaseOut(linear_progress, 0, 1, duration);
case AnimationType.CubicEaseOutIn:
return AnimationMethod.CubicEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseIn:
return AnimationMethod.ElasticEaseIn(linear_progress, 0, 1, duration); case AnimationType.ElasticEaseInOut:
return AnimationMethod.ElasticEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseOut:
return AnimationMethod.ElasticEaseOut(linear_progress, 0, 1, duration);
case AnimationType.ElasticEaseOutIn:
return AnimationMethod.ElasticEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseIn:
return AnimationMethod.ExpoEaseIn(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseInOut:
return AnimationMethod.ExpoEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseOut:
return AnimationMethod.ExpoEaseOut(linear_progress, 0, 1, duration);
case AnimationType.ExpoEaseOutIn:
return AnimationMethod.ExpoEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseIn:
return AnimationMethod.QuadEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseInOut:
return AnimationMethod.QuadEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseOut:
return AnimationMethod.QuadEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuadEaseOutIn:
return AnimationMethod.QuadEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseIn:
return AnimationMethod.QuartEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseInOut:
return AnimationMethod.QuartEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseOut:
return AnimationMethod.QuartEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuartEaseOutIn:
return AnimationMethod.QuartEaseOutIn(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseIn:
return AnimationMethod.QuintEaseIn(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseInOut:
return AnimationMethod.QuintEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseOut:
return AnimationMethod.QuintEaseOut(linear_progress, 0, 1, duration);
case AnimationType.QuintEaseOutIn:
return AnimationMethod.QuintEaseOutIn(linear_progress, 0, 1, duration); case AnimationType.SineEaseIn:
return AnimationMethod.SineEaseIn(linear_progress, 0, 1, duration);
case AnimationType.SineEaseInOut:
return AnimationMethod.SineEaseInOut(linear_progress, 0, 1, duration);
case AnimationType.SineEaseOut:
return AnimationMethod.SineEaseOut(linear_progress, 0, 1, duration);
case AnimationType.SineEaseOutIn:
return AnimationMethod.SineEaseOutIn(linear_progress, 0, 1, duration);
default:
return linear_progress;
}
} /// <summary>
/// 动画开始
/// </summary>
public void AnimationStart()
{
int number = Interlocked.Increment(ref version);
ThreadPool.QueueUserWorkItem(Start, number);
}
/// <summary>
/// 动画结束
/// </summary>
public void AnimationStop()
{
Interlocked.Increment(ref version);
} private void Start(object state)
{
try
{
int number = Convert.ToInt32(state);
float timespan = duration / span;
float currentTime = timespan;
while (currentTime < duration)
{
if (number != version)
break;
Thread.Sleep((int)timespan);
AnimationComing.Invoke(this, new AnimationEventArgs() { NowValue = GetEaseProgress(AnimationType, currentTime) });
currentTime += timespan;
if (currentTime >= duration)
{
Thread.Sleep((int)(duration-currentTime));
AnimationComing.Invoke(this, new AnimationEventArgs() { NowValue = GetEaseProgress(AnimationType, currentTime) });
}
} Interlocked.Decrement(ref version);
}
catch
{ }
}
} public class AnimationEventArgs : EventArgs
{
public float NowValue;
}

自绘控件时,只需要注册AnimationComing事件的处理方法,进行控件重绘。如下:

        animation.AnimationComing += Animation_AnimationComing;

     private void Animation_AnimationComing(object sender, AnimationEventArgs e)
{
easeFunctionValue = e.NowValue;
Invalidate();
}

2D电池控件自绘部分就不贴代码,代码已开源,见文章尾部。总体效果如下:

项目开源地址:https://gitee.com/james_happy/IndustryControls

Winform GDI+ 绘图一:绘制2D电池的更多相关文章

  1. Winform GDI+绘图二:绘制旋转太极图

    大家好,今天有时间给大家带来Winform自绘控件的第二部分,也是比较有意思的一个控件:旋转太极图. 大家可以停下思考一下,如果让你来绘制旋转的太极图,大家有什么样的思路呢?我今天跟大家展示一下,我平 ...

  2. WinForm GDI+ 资料收集

    UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也不能算是好程序.UI编程体现在两个方面, ...

  3. Winform GDI+

    什么是GDI+ GDI (Graphics Device Interface), 是属于绘图方面的 API (Application Programming Interface). 因为应用程序不能直 ...

  4. MFC GDI绘图基础

    一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...

  5. C#-gdi绘图,双缓冲绘图,Paint事件的触发

    一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1  绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...

  6. GDI+ 绘图闪烁解决方法

    闲着没事,准备做一个类似于TeeChart的自定义控件,结果第一步的绘图就把我给难倒了,虽然早就知道GDI绘图的闪烁问题很坑,但是却没有想到如此之坑,折腾了两天,才找到解决方法. 首先在窗体加载的时候 ...

  7. GDI+(一):GDI+ 绘图基础

    一.GDI+绘图基础 编写图形程序时需要使用GDI(Graphics Device Interface,图形设备接口),从程序设计的角度看,GDI包括两部分:一部分是GDI对象,另一部分是GDI函数. ...

  8. Windows GDI绘图基础知识

    一.Windows可以画直线.椭圆线(椭圆圆周上的曲线)和贝塞尔曲线.////////////7 个画线函式是:(1)画直线LineTo    BOOL LineTo(HDC hdc,int nXEn ...

  9. WinForm GDI编程:Graphics画布类

    命名空间: using System.Drawing;//提供对GDI+基本图形功能的访问 using System.Drawing.Drawing2D;//提供高级的二维和矢量图像功能 using ...

随机推荐

  1. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...

  2. php private学习笔记

    类的权限修饰符,放在属性/方法的前面.用来说明属性/方法的权限特点. 三种权限修饰符 private  私有的 public   公共 protected  保护的 privata 的属性.方法只能在 ...

  3. 刚听完CSDN总裁蒋涛先生的学术报告

    主题: 二十年程序人生和我的人才观 第一次参加所谓的"学术报告", 但感觉更多的是蒋总在跟我们分享他个人的成长经验. 按蒋总的话说, 他已经从2000年开始不碰怎么技术了, 所以个 ...

  4. Spring IOC 之注册解析的 BeanDefinition

    2019独角兽企业重金招聘Python工程师标准>>> DefaultBeanDefinitionDocumentReader.processBeanDefinition() 完成 ...

  5. MySQL数据库的套接字文件和pid文件

    MySQL数据库的套接字文件和pid文件 socket文件:当用Unix域套接字方式进行连接时需要的文件. pid文件:MySQL实例的进程ID文件. MySQL表结构文件:用来存放MySQL表结构定 ...

  6. Lucene的FuzzyQuery中用到的Levenshtein Distance(LD)算法

    2019独角兽企业重金招聘Python工程师标准>>> Lucene的FuzzyQuery中用到的Levenshtein Distance(LD)算法 博客分类: java 搜索引擎 ...

  7. Onedrive File Open Problem

    在用Onenote 2016写笔记时,同步到Onedrive后就变成了Internet快捷方式,而且直接打开时会出现提示: 原因 用Onenote客户端在Onedrive上创建的笔记本是一种特殊文件, ...

  8. Code force-CodeCraft-20 (Div. 2) D. Nash Matrix 详解(DFS构造)

    D. Nash Matrix time limit per test2 seconds memory limit per test256 megabytes inputstandard input o ...

  9. CodeForces - 1245 C - Constanze's Machine

    Codeforces Round #597 (Div. 2) Constanze is the smartest girl in her village but she has bad eyesigh ...

  10. UDP广播的客户端和服务器端的代码设计

    实验环境 linux 注意: 使用UDP广播,是客户端发送广播消息,服务器端接收消息.实际上是客户端探测局域网中可用服务器的一种手段.客户端发送,服务器端接收,千万不能弄混淆!!! 为了避免混淆,本文 ...