1.摘抄
从网上查到了一些WinForm中显示GIF动画的方法,其中有一些懒人方法,不管是PictureBox控件、Label控件还是什么的,直接将动画图像丢给它们的Image,又或者添加到资源,你会发现动画要么不动,要么被窗体遮挡后窗体的重画会使动画失效(在Vista系统中百试百灵)。正确显示动画并不是什么难题,只是懒人采用了错误的方法。
System.Drawing命名空间中为我们提供了处理这些包含时间帧的动画图像的密封类ImageAnimator。查看MSDN文档中《ImageAnimator.Animate 方法》的文章时会看到一个不错的范例。我把它摘出来,演示利用ImageAnimator与直接引用资源两种方法的不同。
using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
public class animateImage : Form
{
//动画图像(来自嵌入资源)
Image animatedImage = Image.FromStream(
Assembly.GetAssembly(typeof(animateImage))
.GetManifestResourceStream("ImageAnimatorExample.Animation.gif"));
//是否正在显示动画
bool currentlyAnimating = false;
//开始动画
public void AnimateImage()
{
if (!currentlyAnimating)
{
ImageAnimator.Animate(animatedImage, new EventHandler(this.On
currentlyAnimating = true;
}
}
//动画帧发生更改触发的事件处理代码
private void On
{
//重绘窗体
this.Invalidate();
//Controls[0].Invalidate(); //让窗体上的Label控件重绘
}
protected override void On
{
//开始动画
AnimateImage();
//得到动画的下一帧准备渲染
ImageAnimator.UpdateFrames();
//将这帧画到窗体上
e.Graphics.DrawImage(this.animatedImage, new Point(0, 40));
//为了区分与Label控件而显示的文字
e.Graphics.DrawString("ImageAnimator+On
}
protected override void On
{
//加载一个Label控件,为了区别与ImageAnimator方式显示动画的不同
new Label()
{
AutoSize = false,
Image = animatedImage,
Parent = this,
Location = new Point(0, 10),
Size = animatedImage.Size,
Text = "Label"
};
Text = "ImageAnimator显示动画图像 F1-博客";
//DoubleBuffered = true; //可以开启窗体的双缓冲减少闪烁
base.On
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData.Equals(Keys.F1))
{
System.Diagnostics.Process.Start(
"http://hi.baidu.com/wingingbob/blog/item/97fba0039185527e3912bb1b.html");
}
return base.ProcessCmdKey(ref msg, keyData);
}
//入口点
public static void Main()
{
Application.Run(new animateImage());
}
}
以上的代码大部分来自MSDN,在测试的时候,试着想办法使窗口重绘(比如被其它窗口遮挡)。我在Vista系统下测试,可以较明显的区分出两个动画的不同
2.我自己的处理:
public partial class gifFrm : Form
{
private Image m_img = null;//首先定义私有变量
private EventHandler evtHandler = null;
public gifFrm()
{
InitializeComponent();
}
//重载当前winform的On
protected override void On
{
base.On
if (m_img != null)
{
//获得当前gif动画下一步要渲染的帧。
UpdateImage();
//将获得的当前gif动画需要渲染的帧显示在界面上的某个位置。
e.Graphics.DrawImage(m_img, new Rectangle(145, 140, m_img.Width, m_img.Height));
}
}
//实现Load方法
private void gifFrm_Load(object sender, EventArgs e)
{
evtHandler = new EventHandler(On
string fileName = Application.StartupPath + "\\dsds.gif";//获取要加载的gif动画文件
if (System.IO.File.Exists(fileName) == true)
{
m_img = Image.FromFile(fileName);
BeginAnimate();//调用开始动画方法
}
}
private void BeginAnimate()//开始动画方法
{
if (m_img != null)
{
//当gif动画每隔一定时间后,都会变换一帧那么就会触发一事件,该方法就是将当前image每变换一帧时,都会调用当前这个委托所关联的方法。
ImageAnimator.Animate(m_img, evtHandler);
}
}
private void On
{
this.Invalidate();//该方法中,只是使得当前这个winform重绘,然后去调用该winform的On
}
private void UpdateImage()
{//获得当前gif动画的下一步需要渲染的帧,当下一步任何对当前gif动画的操作都是对该帧进行操作
ImageAnimator.UpdateFrames(m_img);
}
private void StopAnimate()
{//关闭显示动画,该方法可以在winform关闭时,或者某个按钮的触发事件中进行调用,以停止渲染当前gif动画。
m_img = null;
ImageAnimator.StopAnimate(m_img, evtHandler);
}
//关闭动画
private void gifFrm_FormClosing(object sender, FormClosingEventArgs e)
{
StopAnimate();
}
}
(后续实现:终于可以看到gif动画了,如果动画左侧或者上沿再标上一段文字"loading....",这不是和web2,0的效果一样的了么,但是实现起来却复杂的许多。。。)