C# Winform中如何绘制动画示例详解

作者:小y 时间:2022-03-28 13:26:26 

前言

这里介绍一个.net自身携带的类ImageAnimator,这个类类似于控制动画的时间轴,使用ImageAnimator.CanAnimate可以判断一个图片是否为动画,调用ImageAnimator.Animate可以开始播放动画,即每经过一帧的时间触发一次OnFrameChanged委托,我们只要在该委托中将Image的活动帧选至下一帧再迫使界面重绘就可以实现动画效果了。

为了方便以后的使用,我将这些代码整合到了一起,形成一个AnimateImage类,该类提供了CanAnimate、FrameCount、CurrentFrame等属性,以及Play()、Stop()、Reset()等动画常用的方法,代码如下


using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Drawing;  
using System.Drawing.Imaging;  

namespace GifTest  
{  
 /// <summary>  
 /// 表示一类带动画功能的图像。  
 /// </summary>  
 public class AnimateImage  
 {  
   Image image;  
   FrameDimension frameDimension;  
   /// <summary>  
   /// 动画当前帧发生改变时触发。  
   /// </summary>  
   public event EventHandler<EventArgs> OnFrameChanged;  

/// <summary>  
   /// 实例化一个AnimateImage。  
   /// </summary>  
   /// <param name="img">动画图片。</param>  
   public AnimateImage(Image img)  
   {  
     image = img;  

lock (image)  
     {  
       mCanAnimate = ImageAnimator.CanAnimate(image);  
       if (mCanAnimate)  
       {  
         Guid[] guid = image.FrameDimensionsList;  
         frameDimension = new FrameDimension(guid[0]);  
         mFrameCount = image.GetFrameCount(frameDimension);  
       }  
     }  
   }  

bool mCanAnimate;  
   int mFrameCount = 1, mCurrentFrame = 0;  

/// <summary>  
   /// 图片。  
   /// </summary>  
   public Image Image  
   {  
     get { return image; }  
   }  

/// <summary>  
   /// 是否动画。  
   /// </summary>  
   public bool CanAnimate  
   {  
     get { return mCanAnimate; }  
   }  

/// <summary>  
   /// 总帧数。  
   /// </summary>  
   public int FrameCount  
   {  
     get { return mFrameCount; }  
   }  

/// <summary>  
   /// 播放的当前帧。  
   /// </summary>  
   public int CurrentFrame  
   {  
     get { return mCurrentFrame; }  
   }  

/// <summary>  
   /// 播放这个动画。  
   /// </summary>  
   public void Play()  
   {  
     if (mCanAnimate)  
     {  
       lock (image)  
       {  
         ImageAnimator.Animate(image, new EventHandler(FrameChanged));  
       }  
     }  
   }  

/// <summary>  
   /// 停止播放。  
   /// </summary>  
   public void Stop()  
   {  
     if (mCanAnimate)  
     {  
       lock (image)  
       {  
         ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));  
       }  
     }  
   }  

/// <summary>  
   /// 重置动画,使之停止在第0帧位置上。  
   /// </summary>  
   public void Reset()  
   {  
     if (mCanAnimate)  
     {  
       ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));  
       lock (image)  
       {  
         image.SelectActiveFrame(frameDimension, 0);  
         mCurrentFrame = 0;  
       }  
     }  
   }  

private void FrameChanged(object sender, EventArgs e)  
   {  
     mCurrentFrame = mCurrentFrame + 1 >= mFrameCount ? 0 : mCurrentFrame + 1;  
     lock (image)  
     {  
       image.SelectActiveFrame(frameDimension, mCurrentFrame);  
     }  
     if (OnFrameChanged != null)  
     {  
       OnFrameChanged(image, e);  
     }  
   }  
 }  
}

使用如下方法调用:


using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Drawing.Imaging;  
using System.Text;  
using System.Windows.Forms;  

namespace GifTest  
{  
 public partial class Form1 : Form  
 {  
   AnimateImage image;  

public Form1()  
   {  
     InitializeComponent();  
     image = new AnimateImage(Image.FromFile(@"C:\Documents and Settings\Administrator\My Documents\My Pictures\未命名.gif"));  
     image.OnFrameChanged += new EventHandler<EventArgs>(image_OnFrameChanged);  
     SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);  
   }  

void image_OnFrameChanged(object sender, EventArgs e)  
   {  
     Invalidate();  
   }  

private void Form1_Load(object sender, EventArgs e)  
   {  
     image.Play();  
   }  

private void Form1_Paint(object sender, PaintEventArgs e)  
   {  
     lock (image.Image)  
     {  
       e.Graphics.DrawImage(image.Image, new Point(0, 0));  
     }  
   }  

private void button1_Click(object sender, EventArgs e)  
   {  
     if (button1.Text.Equals("Stop"))  
     {  
       image.Stop();  
       button1.Text = "Play";  
     }  
     else
     {  
       image.Play();  
       button1.Text = "Stop";  
     }  
     Invalidate();  
   }  

private void button2_Click(object sender, EventArgs e)  
   {  
     image.Reset();  
     button1.Text = "Play";  
     Invalidate();  
   }  
 }  
}

来源:https://www.cnblogs.com/tuyile006/p/12880641.html

标签:c#,winform,动画
0
投稿

猜你喜欢

  • Java中List集合去重方法以及效率对比

    2021-11-03 00:15:52
  • Java中逆序遍历List集合的实现

    2022-04-03 23:48:13
  • Java中URL传中文时乱码的解决方法

    2022-05-17 02:16:55
  • C#控制图像旋转和翻转的方法

    2023-11-26 08:25:08
  • Java设计模式之工厂模式案例详解

    2023-11-27 20:08:03
  • Java编程中使用throw关键字抛出异常的用法简介

    2023-08-27 17:04:19
  • Java中this和super的区别及this能否调用到父类使用

    2023-01-05 12:03:13
  • PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例

    2023-11-26 15:05:59
  • java动态口令登录实现过程详解

    2022-01-01 10:16:28
  • 微信开发--自定义菜单查询返码乱码的解决方法

    2023-11-25 04:47:55
  • Spring的初始化和XML解析的实现

    2022-12-13 15:50:51
  • SpringBoot集成内存数据库H2的实践

    2023-03-20 22:44:34
  • 一篇文章带你了解JAVA结构化编程详情

    2022-01-15 13:06:34
  • 永久解决idea git log乱码的问题

    2022-01-10 06:13:13
  • 如何在C#9 中使用顶级程序 (top-level)

    2023-08-20 04:13:24
  • 微信跳一跳辅助Java代码实现

    2022-03-31 19:12:03
  • Java实现通讯录管理系统项目

    2022-11-17 02:41:03
  • C#实现获取程序路径方法小结

    2022-05-09 19:40:48
  • c#多线程编程基础

    2021-11-24 23:37:12
  • 阿里云OSS域名配置及简单上传的示例代码

    2022-04-08 19:14:32
  • asp之家 软件编程 m.aspxhome.com