WPF播放GIF控制元件完整程式碼
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。它的作用就是將System.Drawing.Bitmap轉換後得到的BitmapSource賦值給繼承自Image控制元件的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(); } }