C# Winform 显示Gif动图

来源:互联网 发布:网络主播行业分析 编辑:程序博客网 时间:2024/06/09 14:22

转载于
http://www.cnblogs.com/cpw999cn/archive/2009/02/07/1385885.html

原文标题是:C# Winform中绘制动画的方法
以下是原文。


最近在做一个图片查看器,由于使用一般的PctureBox,在性能和缩放控制上都无法满足预期的要求,因此所有组件的呈现均是通过重写控件的OnPaint事件来绘制。在查看gif图片时发现Graphics.DrawImage只呈现第一帧,无法满足预期要求,因此经过摸索寻找到了解决自绘gif的较好办法。

这里介绍一个.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();           }       }   }

有点不完美的地方,在Paint事件中,必须锁定Image,否则很容易出现“对象当前正在其他地方使用。”的异常,因为AnimateImage也在使用这个Image对象。如果你有更好的解决办法,欢迎给我留言~~

原创粉丝点击