在WPF中玩Gif

时间:2015-06-12 12:32:41

标签: c# wpf

我目前正在尝试在WPF中显示和播放GIF动画而没有太多运气

我已经尝试了here找到的所有解决方案,包括问题中的那个

这是我目前拥有的

<Window x:Class="Sooooothing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Attached="clr-namespace:Sooooothing"
    Title="MainWindow" Height="327.861" Width="525">
<Grid>
    <MediaElement x:Name="gif" MediaEnded="myGif_MediaEnded" UnloadedBehavior="Manual" 
                  Source="Images\7c6516d73fc8643abf1df969fcc1a72c.gif" 
                  LoadedBehavior="Play" Stretch="None"/>
</Grid>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Sooooothing
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //gif.Play();
        }
        private void myGif_MediaEnded(object sender, RoutedEventArgs e)
        {
            gif.Position = new TimeSpan(0, 0, 1);
            gif.Play();
        }
    }
}

当应用程序启动时,我得到的是窗口的白色背景,起初我虽然是gif没有加载但我让它坐了几分钟而没有任何改变。

这是我的解决方案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Sooooothing
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        GifBitmapDecoder decoder2;
        int ImageNumber = 0;
        bool mouseIn = true;
        double opasity = 0;
        List<Thread> threadList = new List<Thread>();
        bool programClosed = false;
        public MainWindow()
        {
            InitializeComponent();

            Classes.DataHouse.load(); //Im storing all my gif links in this List<string> so i can 
            // loop through them with buttons on the window

            #region thread gif frame changer
            Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
            decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource2; // Decode the gif using GifBitmapDecoder then start a thread to 
            int frameCount = decoder2.Frames.Count;// loop through all the images and put them one after
            Thread th = new Thread(() => {// another into an image on your window
                while (!programClosed)
                {

                    for (int i = 0; i < frameCount; i++)
                    {
                        try{
                            this.Dispatcher.Invoke(new Action(delegate()
                            {
                                frameCount = decoder2.Frames.Count;
                                if (frameCount >= i)
                                {
                                    bitmapSource2 = decoder2.Frames[i];
                                    image.Source = bitmapSource2;
                                }

                            }));
                        }
                        catch
                        {
                            //the thread was probably aborted
                        }
                        System.Threading.Thread.Sleep(100);
                    }
                }
            });
            threadList.Add(th);
            th.Start();
            #endregion
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
                this.DragMove();
        }

        private void img_forward_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (ImageNumber+1 >= Classes.DataHouse.images.Count)
                ImageNumber = 0;
            else
                ImageNumber++;
            Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
            decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        }

        private void Grid_MouseEnter(object sender, MouseEventArgs e)
        {
            mouseIn = true;
            Thread th = new Thread(() => 
            {
                while (opasity < 100 && mouseIn)
                {
                    System.Threading.Thread.Sleep(25);
                    opasity++;
                    try
                    {
                        this.Dispatcher.Invoke(new Action(delegate()
                        {
                            img_forward.Opacity = opasity / 100;
                            img_exit.Opacity = opasity / 100;
                            img_backward.Opacity = opasity / 100;
                        }));
                    }
                    catch
                    {
                        //the thread was probably aborted
                    }
                }
            });
            threadList.Add(th);
            th.Start();


        }

        private void Grid_MouseLeave(object sender, MouseEventArgs e)
        {
            mouseIn = false;
            Thread th = new Thread(() =>
            {

                while (opasity > 0 && !mouseIn)
                {
                    System.Threading.Thread.Sleep(25);
                    opasity--;
                    try{
                        this.Dispatcher.Invoke(new Action(delegate()
                        {
                            img_forward.Opacity = opasity / 100;
                            img_exit.Opacity = opasity / 100;
                            img_backward.Opacity = opasity / 100;
                        }));
                    }
                    catch
                    {
                        //the thread was probably aborted
                    }
                }
            });
            threadList.Add(th);
            th.Start();
        }

        private void img_backward_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (ImageNumber - 1 < 0)
                ImageNumber = Classes.DataHouse.images.Count-1;
            else
                ImageNumber--;
            Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
            decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        }

        private void img_exit_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            foreach (Thread th in threadList)
            {
                while(th.ThreadState == ThreadState.Running)
                    th.Abort();
            }
            programClosed = true;
            this.Close();
        }

    }
}

3 个答案:

答案 0 :(得分:3)

不幸的是,当微软开发WPF时,动画GIF图像有点疏忽,所以没有内置的&#39;处理这个的功能。在线发现了几个工作示例,但您仍应注意,需要在UI线程上运行代码才能为这些图像设置动画。

因此,在某些情况下,例如尝试使用“忙碌”等。加载过程中的GIF将无法正常工作,因为UI线程已经忙碌。

宣布免责声明之后,您可以在以下链接中找到一些可以在Thomas Levesque的GitHub项目中执行您想要的工作代码:

thomaslevesque/WpfAnimatedGif

答案 1 :(得分:2)

使用线程

public MainWindow()
        {
            InitializeComponent();

            Uri myUri = new Uri(@"Images\2b3601fe2b62e87481bd301da52a2182.gif", UriKind.RelativeOrAbsolute);
            GifBitmapDecoder decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource2;
            int frameCount = decoder2.Frames.Count;

            Thread th = new Thread(() => {
                while (true)
                {
                    for (int i = 0; i < frameCount; i++)
                    {
                        this.Dispatcher.Invoke(new Action(delegate()
                        {
                            bitmapSource2 = decoder2.Frames[i];
                            image.Source = bitmapSource2;
                        }));
                        System.Threading.Thread.Sleep(100);
                    }
                }
            });
            th.Start();
        }

答案 2 :(得分:0)

这仅适用于未编译为资源等的物理文件

尝试更改您的图像资源Build Action to Content或类似内容,而不是资源(并激活Copy to Output Directory,可能?)。

我设法以这种方式工作。关键是你必须引用某个文件夹或互联网URL中的物理文件。

有关详情,请查看:https://social.msdn.microsoft.com/Forums/vstudio/en-US/93d50a97-0d8d-4b18-992e-cd3200693337/how-to-use-an-animated-gif?forum=wpf