WinForm中正確顯示GIF動畫

1.摘抄

從網上查到了一些WinForm中顯示GIF動畫的方法,其中有一些懶人方法,不管是PictureBox控件、Label控件還是什麼的,直接將動畫圖像丟給它們的Image,又或者添加到資源,你會發現動畫要麼不動,要麼被窗體遮擋後窗體的重畫會使動畫失效(在Vista系統中百試百靈)。正確顯示動畫並不是什麼難題,只是懶人採用了錯誤的方法。

System.Drawing命名空間中爲我們提供了處理這些包含時間幀的動畫圖像的密封類ImageAnimator。查看MSDN文檔中《ImageAnimator.Animate 方法》的文章時會看到一個不錯的範例。我把它摘出來,演示利用ImageAnimator與直接引用資源兩種方法的不同。

WinForm中正確顯示GIF動畫 - qiulei_21 - 見證我心

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.OnFrameChanged));    
             currentlyAnimating = true;    
         }    
     }    
   
    //動畫幀發生更改觸發的事件處理代碼    
    private void OnFrameChanged(object o, EventArgs e)    
     {    
        //重繪窗體    
        this.Invalidate();    
        //Controls[0].Invalidate(); //讓窗體上的Label控件重繪    
     }    
   
    protected override void OnPaint(PaintEventArgs e)    
     {    
        //開始動畫    
         AnimateImage();    
        //得到動畫的下一幀準備渲染    
         ImageAnimator.UpdateFrames();    
        //將這幀畫到窗體上    
         e.Graphics.DrawImage(this.animatedImage, new Point(0, 40));    
        //爲了區分與Label控件而顯示的文字    
         e.Graphics.DrawString("ImageAnimator+OnPaint", Font, SystemBrushes.ControlText, new PointF(0, 40));    
     }    
   
    protected override void OnLoad(EventArgs e)    
     {    
        //加載一個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.OnLoad(e);    
     }    
   
    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的OnPaint方法,當界面被重繪時去顯示當前gif顯示的某一幀
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            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(OnImageAnimate);//爲委託關聯一個處理方法
            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 OnImageAnimate(Object sender, EventArgs e)//委託所關聯的方法
        {
            this.Invalidate();//該方法中,只是使得當前這個winform重繪,然後去調用該winform的OnPaint()方法進行重繪)
        }
        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的效果一樣的了麼,但是實現起來卻複雜的許多。。。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章