WPF 如何显示gif

最近碰到了要显示表情的需求,而表情刚好是gif的图片。

于是用了Image试了下,发现不行,只会显示第一帧,然后上网查了下资料,大致有这么几种方法,都可以实现。

第一种:

使用Winfrom里面的picturebox,缺点是要引用几个winfrom的dll

 

第二种:

用wpf的mediaelement控件,这控件本身是用来显示视频的,但是可以拿来放gif,

这种方式有一个局限就是图片路径必须是绝对路径

 <MediaElement Source="file://C:\129.gif" />

 

并且你还需要设置让他循环播放

 

[csharp] view plain copy

  1. <MediaElement Source="file://C:\129.gif" MediaEnded="MediaElement_MediaEnded"/>  
  2.   
  3.   private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)  
  4.   {  
  5.       ((MediaElement)sender).Position=((MediaElement)sender).Position.Add(TimeSpan.FromMilliseconds(1));  
  6.   }  
而且我发现这种方法在win7以上的系统中才能使用,在XP系统下就失效了,所以果断放弃


第三种:

来自周银辉的博客,原文地址:http://www.cnblogs.com/zhouyinhui/archive/2007/12/23/1011555.html

大致的思路是:使用GifBitmapDecoder类,其可以将动态GIF分解成很多帧并保存在一个列表中,每一帧为一个BitmapFrame类型的对象,其父类为BitmapSource,可以将每一帧赋值给一个Image控件的Source属性,这样可以得到针对GIF各帧的Image系列。

 

第四种:就是目前我在用的方法,重写下Wpf的Image控件

来自CH似水年华的博客,原文地址: http://hi.baidu.com/mych/blog/item/1eb14f545f12a752564e00be.html

首先新建一个类继承自Image

 

[csharp] view plain copy

  1. public class GifImage : System.Windows.Controls.Image  
  2. {  
  3. /// <summary>  
  4. /// gif动画的System.Drawing.Bitmap  
  5. /// </summary>  
  6. private Bitmap gifBitmap;  
  7.   
  8. /// <summary>  
  9. /// 用于显示每一帧的BitmapSource  
  10. /// </summary>  
  11. private BitmapSource bitmapSource;  
  12.   
  13. public GifImage(string gifPath)  
  14. {  
  15. this.gifBitmap = new Bitmap(gifPath);  
  16. this.bitmapSource = this.GetBitmapSource();  
  17. this.Source = this.bitmapSource;  
  18. }  
  19.   
  20. /// <summary>  
  21. /// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource  
  22. /// </summary>  
  23. /// <returns></returns>  
  24. private BitmapSource GetBitmapSource()  
  25. {  
  26. IntPtr handle = IntPtr.Zero;  
  27.   
  28. try  
  29. {  
  30. handle = this.gifBitmap.GetHbitmap();  
  31. this.bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());  
  32. }  
  33. finally  
  34. {  
  35. if (handle != IntPtr.Zero)  
  36. {  
  37. DeleteObject(handle);  
  38. }  
  39. }  
  40. return this.bitmapSource;  
  41. }  
  42.   
  43. /// <summary>  
  44. /// Start animation  
  45. /// </summary>  
  46. public void StartAnimate()  
  47. {  
  48. ImageAnimator.Animate(this.gifBitmap, this.OnFrameChanged);  
  49. }  
  50.   
  51. /// <summary>  
  52. /// Stop animation  
  53. /// </summary>  
  54. public void StopAnimate()  
  55. {  
  56. ImageAnimator.StopAnimate(this.gifBitmap, this.OnFrameChanged);  
  57. }  
  58.   
  59. /// <summary>  
  60. /// Event handler for the frame changed  
  61. /// </summary>  
  62. private void OnFrameChanged(object sender, EventArgs e)  
  63. {  
  64. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>  
  65. {  
  66. ImageAnimator.UpdateFrames(); // 更新到下一帧  
  67. if (this.bitmapSource != null)  
  68. {  
  69. this.bitmapSource.Freeze();  
  70. }  
  71.   
  72.  Convert the bitmap to BitmapSource that can be display in WPF Visual Tree  
  73. this.bitmapSource = this.GetBitmapSource();  
  74. Source = this.bitmapSource;  
  75. this.InvalidateVisual();  
  76. }));  
  77. }  
  78.   
  79. /// <summary>  
  80. /// Delete local bitmap resource  
  81. /// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx  
  82. /// </summary>  
  83. [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]  
  84. [return: MarshalAs(UnmanagedType.Bool)]  
  85. static extern bool DeleteObject(IntPtr hObject);  
  86. }   

然后调用方式如下:

 

[csharp] view plain copy

  1. private GifImage gifImage;  
  2.        public MainWindow()  
  3.        {  
  4.            InitializeComponent();  
  5.            this.gifImage = new GifImage("ProgressIndicator.gif");  
  6.            this.gifImage.Width = 100;  
  7.            this.gifImage.Height = 100;  
  8.            this.Content = this.gifImage;  
  9.        }  
  10.   
  11.        private void Window_Loaded(object sender, RoutedEventArgs e)  
  12.        {  
  13.            Popup dd = new Popup();  
  14.            this.gifImage.StartAnimate();  
  15.        }  

经测试,可以在xp下完美显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值