WPF播放GIF动画

2016-09-14 11:19:29来源:CSDN作者:Libby1984人点击

WPF拥有很强的界面设计能力,可以很方便的做出非常漂亮的界面。但有个问题,WPF没有自己的播放GIF的控件。这让很多想在界面播放动态动画的人不得不使用视频来代替。WPF就真的不能播放GIF动图了吗?当然是可以播放的,只是我们需要写一些代码。下面是我总结后写的一个WPF播放GIF动画的控件。

下面介绍一下WPF播放GIF控件思路:

在WinForm里面System.Drawing.Bitmap是可以通过ImageAnimator类来播放GIF动画的,但是可惜的是System.Drawing.Bitmap没有办法直接显示在WPF界面上。于是我们利用ImageAnimator播放System.Drawing.Bitmap对应的GIF动画。在每次System.Drawing.Bitmap上显示的图像改变时,获取当前图像,然后将图像转换为可以在WPF上显示BitmapSource,将转换得来的BitmapSource作为一帧动画显示在界面。

首先我们建立一个命名为GifImage的类,这个类继承自System.Windows.Controls.Image。它的作用就是通过将转换而来的BitmapSource赋值给它的Source属性,在显示GIF图像,根据GIF每一帧的图像改变,GifImage显示的内容也会改变,这样就达到了动态效果。下面是代码,很简单。

public class GifImage : System.Windows.Controls.Image    {        /// <summary>        /// gif动画的System.Drawing.Bitmap        /// </summary>        private Bitmap gifBitmap;        /// <summary>        /// 用于显示每一帧的BitmapSource        /// </summary>        private BitmapSource bitmapSource;        public GifImage(string gifPath)        {            this.gifBitmap = new Bitmap(gifPath);            this.bitmapSource = this.GetBitmapSource();            this.Source = this.bitmapSource;        }        /// <summary>        /// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource        /// </summary>        /// <returns></returns>        private BitmapSource GetBitmapSource()        {            IntPtr handle = IntPtr.Zero;            try            {                handle = this.gifBitmap.GetHbitmap();                this.bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());            }            finally            {                if (handle != IntPtr.Zero)                {                    DeleteObject(handle);                }            }            return this.bitmapSource;        }        /// <summary>        /// Start animation        /// </summary>        public void StartAnimate()        {            ImageAnimator.Animate(this.gifBitmap, this.OnFrameChanged);        }        /// <summary>        /// Stop animation        /// </summary>        public void StopAnimate()        {            ImageAnimator.StopAnimate(this.gifBitmap, this.OnFrameChanged);        }        /// <summary>        /// Event handler for the frame changed        /// </summary>        private void OnFrameChanged(object sender, EventArgs e)        {            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>             {                ImageAnimator.UpdateFrames();  // 更新到下一帧                if (this.bitmapSource != null)                {                    this.bitmapSource.Freeze();                }                //// Convert the bitmap to BitmapSource that can be display in WPF Visual Tree                this.bitmapSource = this.GetBitmapSource();                Source = this.bitmapSource;                this.InvalidateVisual();            }));        }        /// <summary>        /// Delete local bitmap resource        /// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx        /// </summary>        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]        [return: MarshalAs(UnmanagedType.Bool)]        static extern bool DeleteObject(IntPtr hObject);    }

其中ImageAnimator类是通过静态方法Animate和StopAnimate开始和结束System.Drawing.Bitmap所对应的GIF动画。这两个函数的第二个参数是一个委托,当前播放GIF动画每一帧图像发生改变的时候,这个委托所指定的函数就会被触发。那么我们就可以在这个委托里将当前显示的System.Drawing.Bitmap图像转换为在WPF上可以显示的BitmapSource,然后赋值给Source属性显示在界面。

下面是在一个Window中使用GIFInage控件。ProgressIndicator.gif是要播放的GIF文件的文件名,在程序运行目录。

public partial class MainWindow : Window    {        private GifImage gifImage;         public MainWindow()        {            InitializeComponent();            this.gifImage = new GifImage("ProgressIndicator.gif");            this.gifImage.Width = 100;            this.gifImage.Height = 100;            this.Content = this.gifImage;        }        private void Window_Loaded(object sender, RoutedEventArgs e)        {            this.gifImage.StartAnimate();        }    }






最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台