2017-01-16 80 views
-2

下面是標準的d3drenderer.cs文件編碼:可以將xml讀取器功能放入D3drenderer.cs中嗎?

using System; 
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Interop; 
using System.Windows.Media; 
using System.Windows.Threading; 
using System.Xml.Linq; 

namespace WPFMediaKit.DirectShow.Controls 
{ 
    /// <summary> 
    /// The D3DRenderer class provides basic functionality needed 
    /// to render a D3D surface. This class is abstract. 
    /// </summary> 
public abstract class D3DRenderer : FrameworkElement 
{ 
    private string workingDirectory = AppDomain.CurrentDomain.BaseDirectory; 
    /// <summary> 
    /// The D3DImage used to render video 
    /// </summary> 
    private D3DImage m_d3dImage; 

    /// <summary> 
    /// The Image control that has the source 
    /// to the D3DImage 
    /// </summary> 
    private Image m_videoImage; 

    /// <summary> 
    /// We keep reference to the D3D surface so 
    /// we can delay loading it to avoid a black flicker 
    /// when loading new media 
    /// </summary> 
    private IntPtr m_pBackBuffer = IntPtr.Zero; 

    /// <summary> 
    /// Flag to tell us if we have a new D3D 
    /// Surface available 
    /// </summary> 
    private bool m_newSurfaceAvailable; 

    /// <summary> 
    /// A weak reference of D3DRenderers that have been cloned 
    /// </summary> 
    private readonly List<WeakReference> m_clonedD3Drenderers = new List<WeakReference>(); 

    /// <summary> 
    /// Backing field for the RenderOnCompositionTargetRendering flag. 
    /// </summary> 
    private bool m_renderOnCompositionTargetRendering; 

    /// <summary> 
    /// Temporary storage for the RenderOnCompositionTargetRendering flag. 
    /// This is used to remember the value for when the control is loaded and unloaded. 
    /// </summary> 
    private bool m_renderOnCompositionTargetRenderingTemp; 

    #region Stretch 
    public static readonly DependencyProperty StretchProperty = 
     DependencyProperty.Register("Stretch", typeof(Stretch), typeof(D3DRenderer), 
      new FrameworkPropertyMetadata(Stretch.Uniform, 
       new PropertyChangedCallback(OnStretchChanged))); 

    /// <summary> 
    /// Defines what rules are applied to the stretching of the video 
    /// </summary> 
    public Stretch Stretch 
    { 
     get { return (Stretch)GetValue(StretchProperty); } 
     set { SetValue(StretchProperty, value); } 
    } 

    private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((D3DRenderer)d).OnStretchChanged(e); 
    } 

    private void OnStretchChanged(DependencyPropertyChangedEventArgs e) 
    { 
     m_videoImage.Stretch = (Stretch) e.NewValue; 
    } 
    #endregion 

    #region IsRenderingEnabled 

    public static readonly DependencyProperty IsRenderingEnabledProperty = 
     DependencyProperty.Register("IsRenderingEnabled", typeof(bool), typeof(D3DRenderer), 
      new FrameworkPropertyMetadata(true)); 

    /// <summary> 
    /// Enables or disables rendering of the video 
    /// </summary> 
    public bool IsRenderingEnabled 
    { 
     get { return (bool)GetValue(IsRenderingEnabledProperty); } 
     set { SetValue(IsRenderingEnabledProperty, value); } 
    } 

    #endregion 

    #region NaturalVideoHeight 

    private static readonly DependencyPropertyKey NaturalVideoHeightPropertyKey 
     = DependencyProperty.RegisterReadOnly("NaturalVideoHeight", typeof(int), typeof(MediaElementBase), 
      new FrameworkPropertyMetadata(0)); 

    public static readonly DependencyProperty NaturalVideoHeightProperty 
     = NaturalVideoHeightPropertyKey.DependencyProperty; 

    /// <summary> 
    /// Gets the natural pixel height of the current media. 
    /// The value will be 0 if there is no video in the media. 
    /// </summary> 
    public int NaturalVideoHeight 
    { 
     get { return (int)GetValue(NaturalVideoHeightProperty); } 
    } 

    /// <summary> 
    /// Internal method to set the read-only NaturalVideoHeight DP 
    /// </summary> 
    protected void SetNaturalVideoHeight(int value) 
    { 
     SetValue(NaturalVideoHeightPropertyKey, value); 
    } 

    #endregion 

    #region NaturalVideoWidth 

    private static readonly DependencyPropertyKey NaturalVideoWidthPropertyKey 
     = DependencyProperty.RegisterReadOnly("NaturalVideoWidth", typeof(int), typeof(MediaElementBase), 
      new FrameworkPropertyMetadata(0)); 

    public static readonly DependencyProperty NaturalVideoWidthProperty 
     = NaturalVideoWidthPropertyKey.DependencyProperty; 

    /// <summary> 
    /// Gets the natural pixel width of the current media. 
    /// The value will be 0 if there is no video in the media. 
    /// </summary> 
    public int NaturalVideoWidth 
    { 
     get { return (int)GetValue(NaturalVideoWidthProperty); } 
    } 

    /// <summary> 
    /// Internal method to set the read-only NaturalVideoWidth DP 
    /// </summary> 
    protected void SetNaturalVideoWidth(int value) 
    { 
     SetValue(NaturalVideoWidthPropertyKey, value); 
    } 

    #endregion 

    #region HasVideo 

    private static readonly DependencyPropertyKey HasVideoPropertyKey 
     = DependencyProperty.RegisterReadOnly("HasVideo", typeof(bool), typeof(MediaElementBase), 
      new FrameworkPropertyMetadata(false)); 

    public static readonly DependencyProperty HasVideoProperty 
     = HasVideoPropertyKey.DependencyProperty; 

    /// <summary> 
    /// Is true if the media contains renderable video 
    /// </summary> 
    public bool HasVideo 
    { 
     get { return (bool)GetValue(HasVideoProperty); } 
    } 

    /// <summary> 
    /// Internal method for setting the read-only HasVideo DP 
    /// </summary> 
    protected void SetHasVideo(bool value) 
    { 
     SetValue(HasVideoPropertyKey, value); 
    } 
    #endregion 

    protected D3DRenderer() 
    { 
     InitializeD3DVideo(); 

     /* Hook into the framework events */ 
     Loaded += D3DRenderer_Loaded; 
     Unloaded += D3DRenderer_Unloaded; 
    } 

    /// <summary> 
    /// Handler for when the D3DRenderer is unloaded 
    /// </summary> 
    private void D3DRenderer_Unloaded(object sender, RoutedEventArgs e) 
    { 
     /* Remember what the property value was */ 
     m_renderOnCompositionTargetRenderingTemp = RenderOnCompositionTargetRendering; 

     /* Make sure to unhook the static event hook because we are unloading */ 
     RenderOnCompositionTargetRendering = false; 
    } 

    /// <summary> 
    /// Handler for when the D3DRenderer is loaded 
    /// </summary> 
    private void D3DRenderer_Loaded(object sender, RoutedEventArgs e) 
    { 
     /* Restore the property's value */ 
     RenderOnCompositionTargetRendering = m_renderOnCompositionTargetRenderingTemp; 
    } 

    /// <summary> 
    /// Initializes the D3DRenderer control 
    /// </summary> 
    protected virtual void InitializeD3DVideo() 
    { 
     if (m_videoImage != null) 
      return; 

     /* Create our Image and it's D3DImage source */ 
     m_videoImage = new Image(); 
     m_d3dImage = new D3DImage(); 

     /* We hook into this event to handle when a D3D device is lost */ 
     D3DImage.IsFrontBufferAvailableChanged += D3DImage_IsFrontBufferAvailableChanged; 

     /* Set our default stretch value of our video */ 
     m_videoImage.Stretch = (Stretch)StretchProperty.DefaultMetadata.DefaultValue; 
     var activeProfiles = XElement.Load(workingDirectory + "ProfilesDisplay.xml"); 
     var a = activeProfiles.Element("_nABC").Value; 

     /* Our source of the video image is the D3DImage */ 
     m_videoImage.Source = D3DImage; 

     /* Register the Image as a visual child */ 
     AddVisualChild(m_videoImage); 
    } 

    /// <summary> 
    /// This should only fire when a D3D device is lost 
    /// </summary> 
    private void D3DImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     if (!D3DImage.IsFrontBufferAvailable) 
      return; 

     /* Flag that we have a new surface, even 
     * though we really don't */ 
     m_newSurfaceAvailable = true; 

     /* Force feed the D3DImage the Surface pointer */ 
     SetBackBufferInternal(m_pBackBuffer); 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     m_videoImage.Measure(availableSize); 
     return m_videoImage.DesiredSize; 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     m_videoImage.Arrange(new Rect(finalSize)); 
     return finalSize; 
    } 

    protected override int VisualChildrenCount 
    { 
     get 
     { 
      return 1; 
     } 
    } 

    protected override Visual GetVisualChild(int index) 
    { 
     if (index > 0) 
      throw new IndexOutOfRangeException(); 

     return m_videoImage; 
    } 

    protected D3DImage D3DImage 
    { 
     get 
     { 
      return m_d3dImage; 
     } 
    } 

    protected Image VideoImage 
    { 
     get 
     { 
      return m_videoImage; 
     } 
    } 

    /// <summary> 
    /// Renders the video with WPF's rendering using the CompositionTarget.Rendering event 
    /// </summary> 
    protected bool RenderOnCompositionTargetRendering 
    { 
     get 
     { 
      return m_renderOnCompositionTargetRendering; 
     } 
     set 
     { 
      /* If it is being set to true and it was previously false 
      * then hook into the event */ 
      if (value && !m_renderOnCompositionTargetRendering) 
       CompositionTarget.Rendering += CompositionTarget_Rendering; 
      else if(!value) 
       CompositionTarget.Rendering -= CompositionTarget_Rendering; 

      m_renderOnCompositionTargetRendering = value; 
      m_renderOnCompositionTargetRenderingTemp = value; 
     } 
    } 

    private void CompositionTarget_Rendering(object sender, EventArgs e) 
    { 
     InternalInvalidateVideoImage(); 
    } 

    /// <summary> 
    /// Used as a clone for a D3DRenderer 
    /// </summary> 
    private class ClonedD3DRenderer : D3DRenderer 
    {} 

    /// <summary> 
    /// Creates a clone of the D3DRenderer. This is a work for the visual 
    /// brush not working cross-threaded 
    /// </summary> 
    /// <returns></returns> 
    public D3DRenderer CloneD3DRenderer() 
    { 
     var renderer = new ClonedD3DRenderer(); 

     lock(m_clonedD3Drenderers) 
     { 
      m_clonedD3Drenderers.Add(new WeakReference(renderer)); 
     } 

     renderer.SetBackBuffer(m_pBackBuffer); 
     return renderer; 
    } 

    /// <summary> 
    /// Cleans up any dead references we may have to any cloned renderers 
    /// </summary> 
    private void CleanZombieRenderers() 
    { 
     lock(m_clonedD3Drenderers) 
     { 
      var deadObjects = new List<WeakReference>(); 

      for (int i = 0; i < m_clonedD3Drenderers.Count; i++) 
      { 
       if (!m_clonedD3Drenderers[i].IsAlive) 
        deadObjects.Add(m_clonedD3Drenderers[i]); 
      } 

      foreach(var deadGuy in deadObjects) 
      { 
       m_clonedD3Drenderers.Remove(deadGuy); 
      } 
     } 
    } 

    /// <summary> 
    /// Configures D3DImage with a new surface. The back buffer is 
    /// not set until we actually receive a frame, this way we 
    /// can avoid a black flicker between media changes 
    /// </summary> 
    /// <param name="backBuffer">The unmanaged pointer to the Direct3D Surface</param> 
    protected void SetBackBuffer(IntPtr backBuffer) 
    { 
     /* We only do this if target rendering is enabled because we must use an Invoke 
     * instead of a BeginInvoke to keep the Surfaces in sync and Invoke could be dangerous 
     * in other situations */ 
     if(RenderOnCompositionTargetRendering) 
     { 
      if (!D3DImage.Dispatcher.CheckAccess()) 
      { 
       D3DImage.Dispatcher.Invoke((Action)(() => SetBackBuffer(backBuffer)), DispatcherPriority.Render); 
       return; 
      } 
     } 

     /* Flag a new surface */ 
     m_newSurfaceAvailable = true; 
     m_pBackBuffer = backBuffer; 

     /* Make a special case for target rendering */ 
     if (RenderOnCompositionTargetRendering) 
     { 
      SetBackBufferInternal(m_pBackBuffer); 
     } 

     SetBackBufferForClones(); 
    } 

    /// <summary> 
    /// Sets the backbuffer for any cloned D3DRenderers 
    /// </summary> 
    private void SetBackBufferForClones() 
    { 
     lock (m_clonedD3Drenderers) 
     { 
      CleanZombieRenderers(); 

      foreach (var rendererRef in m_clonedD3Drenderers) 
      { 
       var renderer = rendererRef.Target as D3DRenderer; 
       if (renderer != null) 
        renderer.SetBackBuffer(m_pBackBuffer); 
      } 
     } 
    } 

    /// <summary> 
    /// Configures D3DImage with a new surface. This happens immediately 
    /// </summary> 
    private void SetBackBufferInternal(IntPtr backBuffer) 
    { 
     /* Do nothing if we don't have a new surface available */ 
     if (!m_newSurfaceAvailable) 
      return; 

     if(!D3DImage.Dispatcher.CheckAccess()) 
     { 
      D3DImage.Dispatcher.BeginInvoke((Action)(() => SetBackBufferInternal(backBuffer))); 
      return; 
     } 

     /* We have this around a try/catch just in case we 
     * lose the device and our Surface is invalid. The 
     * try/catch may not be needed, but testing needs 
     * to take place before it's removed */ 
     try 
     { 
      D3DImage.Lock(); 
      D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, backBuffer); 
      D3DImage.Unlock(); 
      SetNaturalWidthHeight(); 
     } 
     catch (Exception) 
     { } 

     /* Clear our flag, so this won't be ran again 
     * until a new surface is sent */ 
     m_newSurfaceAvailable = false; 
    } 

    private void SetNaturalWidthHeight() 
    { 
     SetNaturalVideoHeight(m_d3dImage.PixelHeight); 
     SetNaturalVideoWidth(m_d3dImage.PixelWidth); 
    } 

    protected void InvalidateVideoImage() 
    { 
     if (!m_renderOnCompositionTargetRendering) 
      InternalInvalidateVideoImage(); 
    } 

    /// <summary> 
    /// Invalidates the entire Direct3D image, notifying WPF to redraw 
    /// </summary> 
    protected void InternalInvalidateVideoImage() 
    { 
     /* Ensure we run on the correct Dispatcher */ 
     if(!D3DImage.Dispatcher.CheckAccess()) 
     { 
      D3DImage.Dispatcher.BeginInvoke((Action)(() => InvalidateVideoImage())); 
      return; 
     } 

     /* If there is a new Surface to set, 
     * this method will do the trick */ 
     SetBackBufferInternal(m_pBackBuffer); 

     /* Only render the video image if possible, or if IsRenderingEnabled is true */ 
     if (D3DImage.IsFrontBufferAvailable && IsRenderingEnabled && m_pBackBuffer != IntPtr.Zero) 
     { 
      try 
      { 
       /* Invalidate the entire image */ 
       D3DImage.Lock(); 
       D3DImage.AddDirtyRect(new Int32Rect(0, /* Left */ 
                0, /* Top */ 
                D3DImage.PixelWidth, /* Width */ 
                D3DImage.PixelHeight /* Height */)); 
       D3DImage.Unlock(); 
      } 
      catch 
      { } 
     } 

     /* Invalidate all of our cloned D3DRenderers */ 
     InvalidateClonedVideoImages(); 
    } 

    /// <summary> 
    /// Invalidates any possible cloned renderer we may have 
    /// </summary> 
    private void InvalidateClonedVideoImages() 
    { 
     lock(m_clonedD3Drenderers) 
     { 
      CleanZombieRenderers(); 

      foreach(var rendererRef in m_clonedD3Drenderers) 
      { 
       var renderer = rendererRef.Target as D3DRenderer; 
       if(renderer != null) 
        renderer.InvalidateVideoImage(); 
      } 
     } 
    } 
} 

}

InitializeD3DVideo()函數,我嘗試從硬盤的位置讀取XML文件。但它不能完成。

是認爲d3drenderer.cs無法從XML文件中讀取?我只想從xml文件的_nABC中讀取一個值。

+0

的XML可能包含錯誤。要檢查錯誤,將xml發佈到以下視圖中:Project:Add New Item:Xml File。與任何編譯器錯誤一樣,錯誤將顯示在錯誤列表中。 – jdweng

回答

0

這有什麼好做的D3DRenderer。

到XML文件的路徑是錯誤的。還有一個「/」(或「\」)的workingDirectory+ "ProfilesDisplay.xml"之間丟失。 如果你不知道你的路徑字符串,結合這些最好的方法是System.IO.Path.Combine

相關問題