如何在设定的持续时间后调用停止MediaElement?

时间:2014-04-13 16:31:35

标签: c# wpf mediaelement

我在播放gif文件的WPF窗口中添加了一个媒体元素。但我不知道如何在一定的秒数后停止播放GIF。

在我当前的实现中,gif播放指示用户如何在窗口加载时执行操作但我不希望gif在循环中播放,我希望能够在gif之后停止gif秒数。

是否可以通过媒体元素实现这一目标?

private void Window_Loaded(object sender, RoutedEventArgs e)
{
      // set the phrases to listen for and start listening
      listener.Phrases = PhrasesTextBox.Text;
      listener.StartListening();

      gifMediaElement.Play();

}

2 个答案:

答案 0 :(得分:2)

尝试使用AnimatedGIFControl

在WPF中,MediaElement可以显示带有一些不太理想的限制的动画GIF图像:

  1. 必须使用绝对路径设置Source属性;
  2. 默认情况下不支持播放功能;
  3. 透明像素显示为黑色。
  4. 以下是使用AnimatedGIFControl的示例:

    <强> XAML

    <Window x:Class="CSWPFAnimatedGIF.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:CSWPFAnimatedGIF"
            Title="Animated GIF" Height="300" Width="300">
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
    
            <local:AnimatedGIFControl x:Name="GIFCtrl"/>
    
            <Button x:Name="btnStart" Width="70" Height="30" Margin="50" 
                    HorizontalAlignment="Left" Grid.Row="1" Click="btnStart_Click">Start</Button>
    
            <Button x:Name="btnStop" Width="70" Height="30" Margin="50"
                    HorizontalAlignment="Right" Grid.Row="1" Click="btnStop_Click">Stop</Button>        
        </Grid>
    </Window>
    

    <强> Code-behind

    public class AnimatedGIFControl : System.Windows.Controls.Image
    {
        private Bitmap _bitmap; // Local bitmap member to cache image resource
        private BitmapSource _bitmapSource;
        public delegate void FrameUpdatedEventHandler();
    
    
        /// <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)]
        static extern bool DeleteObject(IntPtr hObject);
    
        /// <summary>
        /// Override the OnInitialized method
        /// </summary>
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            this.Loaded += new RoutedEventHandler(AnimatedGIFControl_Loaded);
            this.Unloaded += new RoutedEventHandler(AnimatedGIFControl_Unloaded);           
        }
    
        /// <summary>
        /// Load the embedded image for the Image.Source
        /// </summary>
    
        void AnimatedGIFControl_Loaded(object sender, RoutedEventArgs e)
        {
            // Get GIF image from Resources
            if (Properties.Resources.ProgressIndicator != null)
            {
                _bitmap = Properties.Resources.ProgressIndicator;
                Width = _bitmap.Width;
                Height = _bitmap.Height;
    
                _bitmapSource = GetBitmapSource();
                Source = _bitmapSource;  
            }             
        }
    
        /// <summary>
        /// Close the FileStream to unlock the GIF file
        /// </summary>
        private void AnimatedGIFControl_Unloaded(object sender, RoutedEventArgs e)
        {
            StopAnimate();
        }
    
        /// <summary>
        /// Start animation
        /// </summary>
        public void StartAnimate()
        {
            ImageAnimator.Animate(_bitmap, OnFrameChanged);
        }
    
        /// <summary>
        /// Stop animation
        /// </summary>
        public void StopAnimate()
        {
            ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
        }
    
        /// <summary>
        /// Event handler for the frame changed
        /// </summary>
        private void OnFrameChanged(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                   new FrameUpdatedEventHandler(FrameUpdatedCallback));
        }
    
        private void FrameUpdatedCallback()
        {
            ImageAnimator.UpdateFrames();
    
            if (_bitmapSource != null)
                _bitmapSource.Freeze();
    
            // Convert the bitmap to BitmapSource that can be display in WPF Visual Tree
            _bitmapSource = GetBitmapSource();
            Source = _bitmapSource;
            InvalidateVisual();
        }
    
        private BitmapSource GetBitmapSource()
        {
            IntPtr handle = IntPtr.Zero;                
    
            try
            {
                handle = _bitmap.GetHbitmap();
                _bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
                    handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            finally
            {
                if (handle != IntPtr.Zero)
                    DeleteObject(handle);
            }
    
            return _bitmapSource;
        }
    }
    

    <强> Code Logic

    1. 使用ImageAnimator为具有基于时间的帧的GIF图像设置动画。
    2. 使用InvalidateVisual方法在另一个线程中渲染GIF图像的每一帧。
    3. Image控件派生,以便更容易用作图像控件。
    4. 处理转储资源以确保效率。

答案 1 :(得分:1)

如果您想继续使用MediaElement类型,则一种方法是使用DispatcherTimer。您可以将其设置为在特定秒数内打勾,并关闭计时器和MediaElement。例如:

DispatcherTimer timer = new DispatcherTimer();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    //...
    gifMediaElement.Play();
    timer.Interval = TimeSpan.FromSeconds(5);
    timer.Start();
    timer.Tick += (o, args) =>
    {
        timer.Stop();
        gifMediaElement.Stop();
    };
    //...