How do I get an animated gif to work in WPF?

前端 未结 18 949
广开言路
广开言路 2020-11-22 12:16

What control type should I use - Image, MediaElement, etc.?

相关标签:
18条回答
  • 2020-11-22 12:24

    I, too, did a search and found several different solution in just a thread on the old MSDN forums. (link no longer worked so I removed it)

    The simplest to execute seems to be to use a WinForms PictureBox control, and went like this (changed a few things from the thread, most of it the same).

    Add a reference to System.Windows.Forms, WindowsFormsIntegration, and System.Drawing to your project first.

    <Window x:Class="GifExample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
        xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        Loaded="Window_Loaded" >
        <Grid>
            <wfi:WindowsFormsHost>
                <winForms:PictureBox x:Name="pictureBoxLoading">
                </winForms:PictureBox>
            </wfi:WindowsFormsHost>
        </Grid>
    </Window >
    

    Then in the Window_Loaded handler, you would set the pictureBoxLoading.ImageLocation property to the image file path that you want to show.

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        pictureBoxLoading.ImageLocation = "../Images/mygif.gif";
    }
    

    The MediaElement control was mentioned in that thread, but it is also mentioned that it is a rather heavy control, so there were a number of alternatives, including at least 2 homebrewed controls based on the Image control, so this is the simplest.

    0 讨论(0)
  • 2020-11-22 12:25

    I am not sure if this has been solved but the best way is to use the WpfAnimatedGid library. It is very easy, simple and straight forward to use. It only requires 2lines of XAML code and about 5 lines of C# Code in the code behind.

    You will see all the necessary details of how this can be used there. This is what I also used instead of re-inventing the wheel

    0 讨论(0)
  • 2020-11-22 12:25

    Check my code, I hope this helped you :)

             public async Task GIF_Animation_Pro(string FileName,int speed,bool _Repeat)
                        {
        int ab=0;
                            var gif = GifBitmapDecoder.Create(new Uri(FileName), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                            var getFrames = gif.Frames;
                            BitmapFrame[] frames = getFrames.ToArray();
                            await Task.Run(() =>
                            {
    
    
                                while (ab < getFrames.Count())
                                {
                                    Thread.Sleep(speed);
    try
    {
                                    Dispatcher.Invoke(() =>
                                    {
                                        gifImage.Source = frames[ab];
                                    });
                                    if (ab == getFrames.Count - 1&&_Repeat)
                                    {
                                        ab = 0;
    
                                    }
                                    ab++;
                }
     catch
    {
    }
    
                                }
                            });
                        }
    

    or

         public async Task GIF_Animation_Pro(Stream stream, int speed,bool _Repeat)
                {
     int ab = 0;   
                    var gif = GifBitmapDecoder.Create(stream , BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                    var getFrames = gif.Frames;
                    BitmapFrame[] frames = getFrames.ToArray();
                    await Task.Run(() =>
                    {
    
    
                        while (ab < getFrames.Count())
                        {
                            Thread.Sleep(speed);
        try
        {
    
    
                         Dispatcher.Invoke(() =>
                            {
                                gifImage.Source = frames[ab];
                            });
                            if (ab == getFrames.Count - 1&&_Repeat)
                            {
                                ab = 0;
    
                            }
                            ab++;
        }
         catch{} 
    
    
    
                        }
                    });
                }
    
    0 讨论(0)
  • 2020-11-22 12:26

    I had this issue, until I discovered that in WPF4, you can simulate your own keyframe image animations. First, split your animation into a series of images, title them something like "Image1.gif", "Image2,gif", and so on. Import those images into your solution resources. I'm assuming you put them in the default resource location for images.

    You are going to use the Image control. Use the following XAML code. I've removed the non-essentials.

    <Image Name="Image1">
       <Image.Triggers>
          <EventTrigger RoutedEvent="Image.Loaded"
             <EventTrigger.Actions>
                <BeginStoryboard>
                   <Storyboard>
                       <ObjectAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="Source" RepeatBehavior="Forever">
                          <DiscreteObjectKeyFrames KeyTime="0:0:0">
                             <DiscreteObjectKeyFrame.Value>
                                <BitmapImage UriSource="Images/Image1.gif"/>
                             </DiscreteObjectKeyFrame.Value>
                          </DiscreteObjectKeyFrames>
                         <DiscreteObjectKeyFrames KeyTime="0:0:0.25">
                            <DiscreteObjectKeyFrame.Value>
                               <BitmapImage UriSource="Images/Image2.gif"/>
                            </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrames>
                         <DiscreteObjectKeyFrames KeyTime="0:0:0.5">
                            <DiscreteObjectKeyFrame.Value>
                               <BitmapImage UriSource="Images/Image3.gif"/>
                            </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrames>
                         <DiscreteObjectKeyFrames KeyTime="0:0:0.75">
                            <DiscreteObjectKeyFrame.Value>
                               <BitmapImage UriSource="Images/Image4.gif"/>
                            </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrames>
                         <DiscreteObjectKeyFrames KeyTime="0:0:1">
                            <DiscreteObjectKeyFrame.Value>
                               <BitmapImage UriSource="Images/Image5.gif"/>
                            </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrames>
                      </ObjectAnimationUsingKeyFrames>
                   </Storyboard>
                </BeginStoryboard>
             </EventTrigger.Actions>
          </EventTrigger>
       </Image.Triggers>
    </Image>
    
    0 讨论(0)
  • 2020-11-22 12:26

    Small improvement of GifImage.Initialize() method, which reads proper frame timing from GIF metadata.

        private void Initialize()
        {
            _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    
            int duration=0;
            _animation = new Int32AnimationUsingKeyFrames();
            _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(0, KeyTime.FromTimeSpan(new TimeSpan(0))));
            foreach (BitmapFrame frame in _gifDecoder.Frames)
            {
                BitmapMetadata btmd = (BitmapMetadata)frame.Metadata;
                duration += (ushort)btmd.GetQuery("/grctlext/Delay");
                _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(_gifDecoder.Frames.IndexOf(frame)+1, KeyTime.FromTimeSpan(new TimeSpan(duration*100000))));
            }            
             _animation.RepeatBehavior = RepeatBehavior.Forever;
            this.Source = _gifDecoder.Frames[0];            
            _isInitialized = true;
        }
    
    0 讨论(0)
  • 2020-11-22 12:29

    Basically the same PictureBox solution above, but this time with the code-behind to use an Embedded Resource in your project:

    In XAML:

    <WindowsFormsHost x:Name="_loadingHost">
      <Forms:PictureBox x:Name="_loadingPictureBox"/>
    </WindowsFormsHost>
    

    In Code-Behind:

    public partial class ProgressIcon
    {
        public ProgressIcon()
        {
            InitializeComponent();
            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("My.Namespace.ProgressIcon.gif");
            var image = System.Drawing.Image.FromStream(stream);
            Loaded += (s, e) => _loadingPictureBox.Image = image;
        }
    }
    
    0 讨论(0)
提交回复
热议问题