CSharp Tips:在Form中显示动画图片

在Windows Form的程序中有的时候需要显示动画,例如连接网络的动态图标。传统的做法可能是做一组BMP表示不同的状态,然后在Form上添加一个定时器,隔若干毫秒,绘制下一幅图片,如此循环。但是只能是BMP,没法自动支持本身有动画效果的Gif格式的图片。
在DotNET中有一个ImageAnimator类,动画处理包含基于时间的帧的图像,这样的在C#中就不需要加载一组图片了,一个Gif轻松搞定,程序也干净很多。
 
ImageAnimator类
这个类非常简单,主要有几个方法
1)Animator,启动一个多帧的图片,开始动画显示。这里需要制定一个回调函数onFrameChangedHandler,当图片内部间隔时间达到时触发,通常在这个回调函数中刷新界面,显示下一帧图片。特别强调一点,可能ImageAnimator内部用线呈池的定时器检查时间间隔,所以该回调函数触发时,不在程序的主线程中,要注意同步的问题。
2)CanAnimator方法,判断图片是否是动画图片。
3)StopAnimator方法,比较简单,就是停止正在运行的动画。
4)UpdateFrame方法,使该帧在当前正被动画处理的所有图像中前移。新帧在下一次呈现图像时绘制。如(1)所述onFrameChangedHandler不是在主线程中被触发,所以利用这个事件调用UpdateFrame时一定要考虑同步,如果在绘制图片的同时调用UpdateFrame,或者在调用UpdateFrame时绘制图片都会产生资源冲突的异常。所以建议UpdateFrame和绘制图片的动作都在主线程中去执行。
 
一个完整的示例
显示动画图片的思路是,加载图片,然后调用ImageAnimator.Animator方法,同时指定onFrameChangedHandler毁掉函数;onFrameChangedHandler被触发时重绘界面;在窗口绘制时,调用UpdateFrame,然后绘制图片。
代码如下:
using  System;
using  System.Drawing;
using  System.Collections;
using  System.ComponentModel;
using  System.Windows.Forms;
using  System.Data;
using  System.Diagnostics;
 
namespace  Graphics
{
 
/// <summary>
 
/// Summary description for Form1.
 
/// </summary>

 public class Form1 : System.Windows.Forms.Form
 
{
  
/// <summary>
  
/// Required designer variable.
  
/// </summary>

  private System.ComponentModel.Container components = null;
 
  
private Image   m_imgImage = null;
  
private EventHandler m_evthdlAnimator = null;
 
  
public Form1()
  
{
   
//
   
// Required for Windows Form Designer support
   
//
   InitializeComponent();
   
this.SetStyle(ControlStyles.UserPaint,true);
   
this.SetStyle(ControlStyles.DoubleBuffer,true);
   
this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
 
   
//
   
// TODO: Add any constructor code after InitializeComponent call
   
//
   m_evthdlAnimator = new EventHandler(OnImageAnimate);
   Debug.Assert(m_evthdlAnimator 
!= null);
  }

 
  
/// <summary>
  
/// Clean up any resources being used.
  
/// </summary>

  protected override void Dispose( bool disposing )
  
{
   
if( disposing )
   
{
    
if (components != null
    
{
     components.Dispose();
    }

   }

   
base.Dispose( disposing );
  }

 
  
protected override void OnPaint(PaintEventArgs e)
  
{
   
base.OnPaint (e);
 
   
if (m_imgImage != null)
   
{
    UpdateImage();
    
// 绘制图片的当前帧
    e.Graphics.DrawImage(m_imgImage,new Rectangle(10,10,m_imgImage.Width,m_imgImage.Height));
   }

  }

 
  
protected override void OnLoad(EventArgs e)
  
{
   
base.OnLoad (e);
 
   m_imgImage 
= Image.FromFile("10.gif"); // 加载测试用的Gif图片
   BeginAnimate();
  }

 
 
 
  
Windows Form Designer generated code
 
  
/// <summary>
  
/// The main entry point for the application.
  
/// </summary>

  [STAThread]
  
static void Main() 
  
{
   Application.Run(
new Form1());
  }

 
  
private void Form1_Closed(object sender, System.EventArgs e)
  
{
   
if (m_imgImage != null)
   
{
    StopAnimate();
    m_imgImage 
= null;
   }

  }

 
  
functions of animator image // End of functions of animator image
 
 }

}

最后还有一点注意事项
动画图片的绘制可能会比较频繁,由此造成闪烁,解决办法有两个:
1)不要调用 this.Invalid()重绘整个窗口,而应该调用 this.Invalid(rect)仅绘制显示图形的区域。
2)指定一下窗口风格,启动窗口的双缓存。
   this.SetStyle(ControlStyles.UserPaint,true);
   this.SetStyle(ControlStyles.DoubleBuffer,true);
   this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
 
 
参考文档
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值