2010-01-13 13 views
5

Estoy intentando crear un complemento de visualización de Windows Media Player (WMP) en C#. Soy bastante nuevo para exponer C# a COM y puede haber perdido algo básico. He insistido con esto durante 3 días (unas 20 horas) y no he superado el único problema que describiré a continuación.C# Com Interop con Windows Media Player Visualización (con código de muestra)

Para quienes no lo sepan, las visualizaciones de WMP son las bonitas imágenes que se muestran en el reproductor multimedia mientras se escucha música.

En pocas palabras: WMP llamará a ciertos métodos en mi interfaz C# COM, pero no a otros.

he instalado WMP 11

Me descargado la última Windows SDK que contiene un asistente plug-in C++ para compilar una muestra de la visualización de trabajo. Esta muestra se registra y funciona sin problemas en WMP.

El kit de desarrollo contiene un archivo de encabezado C++ llamado effects.h que contiene 2 interfaces que deben implementarse para que el complemento funcione con WMP. No parece mucho más complicado que eso.

aquí están

MIDL_INTERFACE("D3984C13-C3CB-48e2-8BE5-5168340B4F35") 
IWMPEffects : public IUnknown 
{ 
public: 
    virtual /* [helpstring][local] */ HRESULT STDMETHODCALLTYPE Render( 
     /* [in] */ TimedLevel *pLevels, 
     /* [in] */ HDC hdc, 
     /* [in] */ RECT *prc) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE MediaInfo( 
     /* [in] */ LONG lChannelCount, 
     /* [in] */ LONG lSampleRate, 
     /* [in] */ BSTR bstrTitle) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetCapabilities( 
     /* [out] */ DWORD *pdwCapabilities) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetTitle( 
     /* [out] */ BSTR *bstrTitle) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPresetTitle( 
     /* [in] */ LONG nPreset, 
     /* [out] */ BSTR *bstrPresetTitle) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPresetCount( 
     /* [out] */ LONG *pnPresetCount) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetCurrentPreset( 
     /* [in] */ LONG nPreset) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetCurrentPreset( 
     /* [out] */ LONG *pnPreset) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DisplayPropertyPage( 
     /* [in] */ HWND hwndOwner) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GoFullscreen( 
     /* [in] */ BOOL fFullScreen) = 0; 

    virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RenderFullScreen( 
     /* [in] */ TimedLevel *pLevels) = 0; 

}; 

MIDL_INTERFACE("695386EC-AA3C-4618-A5E1-DD9A8B987632") 
IWMPEffects2 : public IWMPEffects 
{ 
public: 
    virtual HRESULT STDMETHODCALLTYPE SetCore( 
     /* [in] */ IWMPCore *pPlayer) = 0; 

    virtual HRESULT STDMETHODCALLTYPE Create( 
     /* [in] */ HWND hwndParent) = 0; 

    virtual HRESULT STDMETHODCALLTYPE Destroy(void) = 0; 

    virtual HRESULT STDMETHODCALLTYPE NotifyNewMedia( 
     /* [in] */ IWMPMedia *pMedia) = 0; 

    virtual HRESULT STDMETHODCALLTYPE OnWindowMessage( 
     /* [in] */ UINT msg, 
     /* [in] */ WPARAM WParam, 
     /* [in] */ LPARAM LParam, 
     /* [in] */ LRESULT *plResultParam) = 0; 

    virtual HRESULT STDMETHODCALLTYPE RenderWindowed( 
     /* [in] */ TimedLevel *pData, 
     /* [in] */ BOOL fRequiredRender) = 0; 

}; 

Como ya he mencionado, mi conocimiento COM no es mi ser el mejor. Esto es lo que hice para portarlo a C#.

que convierte las interfaces de seguir

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace WmpTestPlugin 
{ 

    [ComVisible(true)] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("D3984C13-C3CB-48e2-8BE5-5168340B4F35")] 
    public interface IWmpEffects 
    { 
     int Render(ref TimedLevel pLevels, IntPtr Hdc, ref RECT pRC); 
     int MediaInfo(int lChannelCount, int lSampleRate, string bstrTitle); 
     int GetCapabilities(ref int pdwCapabilities); 
     int GetTitle(ref string bstrTitle); 
     int GetPresetTitle([In] int nPreset, [MarshalAs(UnmanagedType.BStr)] ref string bstrPresetTitle); 
     int GetPresetCount(ref int count); 
     int SetCurrentPreset(int currentpreset); 
     int GetCurrentPreset(ref int currentpreset); 
     int DisplayPropertyPage(IntPtr hwndOwner); 
     int GoFullScreen(bool fFullscreen); 
     int RenderFullScreen(ref TimedLevel pLevels); 
    } 

    [ComVisible(true)] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("695386EC-AA3C-4618-A5E1-DD9A8B987632")] 
    public interface IWmpEffects2 : IWmpEffects 
    { 
     int SetCore(IntPtr pPlayer); 
     int Create(IntPtr hwndParent); 
     int Destroy(); 
     int NotifyNewMedia(IntPtr pMedia); 
     int OnWindowMessage(int Msg, int WParam, int LParam, ref int plResultParam); 
     int RenderWindowed(ref TimedLevel pData, bool fRequiredRender); 
    } 

    [ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct Data 
    { 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] 
     public byte[] Data0; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] 
     public byte[] Data1; 
    } 

    [ComVisible(true)] 
    public enum PlayerState 
    { 
     Stop_State, 
     Pause_State, 
     Play_State 
    } 

    [ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct TimedLevel 
    { 
     public Data Frequency; 
     public Data Waveform; 
     public PlayerState State; 
     public long TimeStamp; 
    } 

    [ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 
} 

El código para la clase que implementa las interfaces general es la siguiente

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using WmpTestPlugin; 
using System.IO; 
using System.Windows.Forms; 



    [ComVisible(true)] 
    [Guid("C476FF24-5E5C-419d-9110-05EC2EED8511")] 
    //[ProgId("WmpTestPlugin.WmpTest")] 
    [ClassInterface(ClassInterfaceType.None)] 
    public class TestPlugin : IWmpEffects2 
    { 
     [DllImport("user32.dll", EntryPoint = "GetClientRect")] 
     private static extern bool getClientRect(IntPtr windowHandle, ref IntPtr rectangle); 

     private const int EFFECT_CANGOFULLSCREEN = 1; 
     private const int EFFECT_HASPROPERTYPAGE = 2; 

     private const int S_OK = 0; 
     private const int S_FALSE = 1; 
     private const int E_ABORT = unchecked((int)0x80004004); 
     private const int E_ACCESSDENIED = unchecked((int)0x80070005); 
     private const int E_FAIL = unchecked((int)0x80004005); 
     private const int E_HANDLE = unchecked((int)0x80070006); 
     private const int E_INVALIDARG = unchecked((int)0x80070057); 
     private const int E_NOINTERFACE = unchecked((int)0x80004002); 
     private const int E_NOTIMPL = unchecked((int)0x80004001); 
     private const int E_OUTOFMEMORY = unchecked((int)0x8007000E); 
     private const int E_POINTER = unchecked((int)0x80004003); 
     private const int E_UNEXPECTED = unchecked((int)0x8000FFFF); 


     public TestPlugin() 
     { 
      _parentHwnd = IntPtr.Zero; 
      _preset = 0; 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : Construct{1}", DateTime.Now.ToString(), Environment.NewLine)); 

     } 

     ~TestPlugin() 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : Deconstruct{1}", DateTime.Now.ToString(), Environment.NewLine)); 
     } 

     #region IWmpEffects2 Members 

     /// <summary> 
     /// Set WMP core interface 
     /// </summary> 
     /// <param name="pPlayer"></param> 
     /// <returns></returns> 
     public int SetCore(IntPtr pPlayer) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : SetCore{1}", DateTime.Now.ToString(), Environment.NewLine)); 

      // release any existing WMP core interfaces 
      //ReleaseCore(); 

      if (pPlayer == IntPtr.Zero) 
       return S_OK; 

      _playerCore = pPlayer; 

      //connect up any events 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when the visualization should be initialized. 
     /// 
     /// If hwndParent != NULL, RenderWindowed() will be called and the visualization 
     /// should draw into the window specified by hwndParent. This will be the 
     /// behavior when the visualization is hosted in a window. 
     /// 
     /// If hwndParent == NULL, Render() will be called and the visualization 
     /// should draw into the DC passed to Render(). This will be the behavior when 
     /// the visualization is hosted windowless (like in a skin for example). 
     /// </summary> 
     /// <param name="hwndParent"></param> 
     /// <returns></returns> 
     public int Create(IntPtr hwndParent) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : Create{1}", DateTime.Now.ToString(), Environment.NewLine)); 

      _parentHwnd = hwndParent; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when the visualization should be released. 
     /// Any resources allocated for rendering should be released. 
     /// </summary> 
     /// <returns></returns> 
     public int Destroy() 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : Destroy{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      _parentHwnd = IntPtr.Zero; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a new media stream begins playing. 
     /// The visualization can inspect this object for properties (like name or artist) 
     /// that might be interesting for visualization. 
     /// </summary> 
     /// <param name="pMedia"></param> 
     /// <returns></returns> 
     public int NotifyNewMedia(IntPtr pMedia) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : NotifyNewMedia{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      return S_OK; 
     } 

     /// <summary> 
     /// Window messages sent to the parent window. 
     /// </summary> 
     /// <param name="Msg"></param> 
     /// <param name="WParam"></param> 
     /// <param name="LParam"></param> 
     /// <param name="plResultParam"></param> 
     /// <returns></returns> 
     public int OnWindowMessage(int Msg, int WParam, int LParam, ref int plResultParam) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : OnWindowMessage{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      // return S_OK only if the plugin has handled the window message 
      // return S_FALSE to let the defWindowProc handle the message 

      //if (_parentHwnd == IntPtr.Zero) 
       //m_NonWindowedRenderer.OnWindowMessage(&m_RenderContext, msg, WParam, LParam, plResultParam); 
      //else 
      // m_WindowedRenderer.OnWindowMessage(&m_RenderContext, msg, WParam, LParam, plResultParam); 

      return S_FALSE; 
     } 

     /// <summary> 
     /// Called when an effect should render itself to the screen. 
     /// The fRequiredRender flag specifies if an update is required, otherwise the 
     /// update is optional. This allows visualizations that are fairly static (for example, 
     /// album art visualizations) to only render when the parent window requires it, 
     /// instead of n times a second for dynamic visualizations. 
     /// </summary> 
     /// <param name="pData"></param> 
     /// <param name="fRequiredRender"></param> 
     /// <returns></returns> 
     public int RenderWindowed(ref TimedLevel pData, bool fRequiredRender) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : RenderWindowed{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      //windowed 

      // NULL parent window should not happen 
      if (_parentHwnd == IntPtr.Zero) 
       return E_UNEXPECTED; 

      //RECT rect = new RECT(); 

      //TestPlugin.getClientRect(_parentHwnd, ref rect); 

      //do render// 

      return S_OK; 
     } 

     #endregion 

     #region IWmpEffects Members 

     /// <summary> 
     /// Called when an effect should render itself to the screen. 
     /// </summary> 
     /// <param name="pLevels"></param> 
     /// <param name="Hdc"></param> 
     /// <param name="pRC"></param> 
     /// <returns></returns> 
     public int Render(ref TimedLevel pLevels, IntPtr Hdc, ref RECT pRC) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : Render{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      //not windowed 


      //do render 
      return S_OK; 
     } 

     /// <summary> 
     /// Everytime new media is loaded, this method is called to pass the 
     /// number of channels (mono/stereo), the sample rate of the media, and the 
     /// title of the media 
     /// </summary> 
     /// <param name="lChannelCount"></param> 
     /// <param name="lSampleRate"></param> 
     /// <param name="bstrTitle"></param> 
     /// <returns></returns> 
     public int MediaInfo(int lChannelCount, int lSampleRate, string bstrTitle) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : MediaInfo{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      return S_OK; 
     } 

     /// <summary> 
     /// Returns the capabilities of this effect. Flags that can be returned are: 
     /// EFFECT_CANGOFULLSCREEN -- effect supports full-screen rendering 
     /// EFFECT_HASPROPERTYPAGE -- effect supports a property page 
     /// </summary> 
     /// <param name="pdwCapabilities"></param> 
     /// <returns></returns> 
     public int GetCapabilities(ref int pdwCapabilities) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GetCapabilities{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      //no capabilities 
      pdwCapabilities = EFFECT_HASPROPERTYPAGE; 

      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a host wants to obtain the title of the effect 
     /// </summary> 
     /// <param name="bstrTitle"></param> 
     /// <returns></returns> 
     public int GetTitle(ref string bstrTitle) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GetTitle{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      bstrTitle = "Test Wmp C# Plugin"; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a host wants to obtain the title of the given preset 
     /// </summary> 
     /// <param name="nPreset"></param> 
     /// <param name="bstrPresetTitle"></param> 
     /// <returns></returns> 
     public int GetPresetTitle(int nPreset, ref string bstrPresetTitle) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GetPresetTitle{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      //bstrPresetTitle = "Default"; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a host wants to obtain the number of supported presets 
     /// </summary> 
     /// <param name="count"></param> 
     /// <returns></returns> 
     public int GetPresetCount(ref int count) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GetPresetCount{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      count = 1; 
      return S_OK; 
     } 



     /// <summary> 
     /// Invoked when a host wants to obtain the index of the current preset 
     /// </summary> 
     /// <param name="currentpreset"></param> 
     /// <returns></returns> 
     public int SetCurrentPreset(int currentpreset) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : SetCurrentPreset{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      _preset = currentpreset; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a host wants to obtain the index of the current preset 
     /// </summary> 
     /// <param name="currentpreset"></param> 
     /// <returns></returns> 
     public int GetCurrentPreset(ref int currentpreset) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GetCurrentPreset{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      currentpreset = _preset; 
      return S_OK; 
     } 

     /// <summary> 
     /// Invoked when a host wants to display the property page for the effect 
     /// </summary> 
     /// <param name="hwndOwner"></param> 
     /// <returns></returns> 
     public int DisplayPropertyPage(IntPtr hwndOwner) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : DisplayPropertyPage, Owner={1}{2}", DateTime.Now.ToString(), hwndOwner.ToString(), Environment.NewLine)); 
      MessageBox.Show("Hello Me!"); 
      return S_OK; 
     } 

     public int GoFullScreen(bool fFullscreen) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : GoFullScreen{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      return S_OK; 
     } 

     public int RenderFullScreen(ref TimedLevel pLevels) 
     { 
      File.AppendAllText("C:\\wmp.txt", string.Format("{0} : RenderFullScreen{1}", DateTime.Now.ToString(), Environment.NewLine)); 
      return S_OK; 
     } 

     #endregion 

     private IntPtr _parentHwnd; 
     private int _preset; 

     private IntPtr _playerCore; 

    } 

Como se puede ver mi código es bastante vacío, nada más que los trozos de verdad . Mi depuración es simple pero hace el trabajo.

Una vez que esto se compila con un nombre seguro que pueda ser registrado:

regasm assemblyname.dll/TLB

luego se dejó caer en la GAC.

Abrir regedit y añadir la siguiente Info:

Bajo HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ MediaPlayer \ Objects \ Efectos

Nueva clave: WmpTestPlugin

Bajo la nueva clave agrega una nueva cadena valor: Nombre: classid Valor: {C47 6FF24-5E5C-419d-9110-05EC2EED8511}

Así hemos construido un plugin que se ajusta a las interfaces, lo registró en la GAC ​​y dijo reproductor multimedia que está ahí.

Si abre el reproductor multimedia y hace clic derecho en el espacio de visualización, aparecerá un menú. En ese menú será nuestro nuevo plugin.Cuando mueva el mouse hacia abajo al nuevo elemento, WMP llamará al GetPresetCount en el complemento (esto se registrará en el archivo). Entonces se supone que WMP llama al GetPresetTitle pero NUNCA lo hace por mí.

Si abre herramientas \ opciones en la barra de menú y selecciona la pestaña Complementos, puede seleccionar el nuevo complemento. Si hace clic en Propiedades, WMP llamará a GetCapabilities, luego DisplayPropertyPage y aparecerá un cuadro de mensaje del complemento. WMP luego se cuelga. En la versión de C++ FinalConstruct() se llama en una interfaz CComCoClass - No tengo esto y no sé de qué se trata. Creo que puede ser un nivel inferior al que estoy usando?

He intentado muchas cosas para que esto funcione, incluido el cambio de las declaraciones de métodos. Por favor alguien puede mirarlo y ayudar. He buscado en toda la web una solución y no he encontrado nada.

Gracias por leer, Nanook

+0

Para probar esto un poco más he creado una aplicación de Visual Basic 6 (COM), si me refiero a mi C# plugin y el C++ plug-in (de trabajo) que se puede llamar ** GetPresetCount ** luego ** GetPresetTitle ** y reciba mi mensaje de regreso sin problema. Esto al menos me dice que los tipos de referencia son correctos, pero no que la interfaz sea 100% precisa o que COM esté configurado correctamente para que WMP lo vea. – Nanook

+0

Por favor alguien puede intentar esto. O simplemente vota como una buena pregunta. – Nanook

Respuesta

6

Después de mirar un poco de código de interoperabilidad de Windows Shell descubrí que yo debería haber estado usando [ComImport] y no [ComVisible] para las interfaces. Para hacer que las firmas sean iguales a las ya registradas, utilicé [PreserveSig]. La herencia de la interfaz también necesitaba ayuda al redeclar la interfaz base dentro del padre.

Espero que esto ayude a alguien.

Aquí está la clase obrera

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace WmpTestPlugin 
{ 
    [ComImport] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("695386EC-AA3C-4618-A5E1-DD9A8B987632")] 
    public interface IWmpEffects2 : IWmpEffects 
    { 
     [PreserveSig] 
     new int Render(ref TimedLevel pLevels, IntPtr Hdc, ref RECT pRC); 
     [PreserveSig] 
     new int MediaInfo(int lChannelCount, int lSampleRate, string bstrTitle); 
     [PreserveSig] 
     new int GetCapabilities(ref int pdwCapabilities); 
     [PreserveSig] 
     new int GetTitle(ref string bstrTitle); 
     [PreserveSig] 
     new int GetPresetTitle(int nPreset, ref string bstrPresetTitle); 
     [PreserveSig] 
     new int GetPresetCount(ref int count); 
     [PreserveSig] 
     new int SetCurrentPreset(int currentpreset); 
     [PreserveSig] 
     new int GetCurrentPreset(ref int currentpreset); 
     [PreserveSig] 
     new int DisplayPropertyPage(IntPtr hwndOwner); 
     [PreserveSig] 
     new int GoFullScreen(bool fFullscreen); 
     [PreserveSig] 
     new int RenderFullScreen(ref TimedLevel pLevels); 

     [PreserveSig] 
     int SetCore(IntPtr pPlayer); 
     [PreserveSig] 
     int Create(IntPtr hwndParent); 
     [PreserveSig] 
     int Destroy(); 
     [PreserveSig] 
     int NotifyNewMedia(IntPtr pMedia); 
     [PreserveSig] 
     int OnWindowMessage(int Msg, int WParam, int LParam, ref int plResultParam); 
     [PreserveSig] 
     int RenderWindowed(ref TimedLevel pData, bool fRequiredRender); 
    } 

    [ComImport] 
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
    [Guid("D3984C13-C3CB-48e2-8BE5-5168340B4F35")] 
    public interface IWmpEffects 
    { 
     [PreserveSig] 
     int Render(ref TimedLevel pLevels, IntPtr Hdc, ref RECT pRC); 
     [PreserveSig] 
     int MediaInfo(int lChannelCount, int lSampleRate, string bstrTitle); 
     [PreserveSig] 
     int GetCapabilities(ref int pdwCapabilities); 
     [PreserveSig] 
     int GetTitle(ref string bstrTitle); 
     [PreserveSig] 
     int GetPresetTitle(int nPreset, ref string bstrPresetTitle); 
     [PreserveSig] 
     int GetPresetCount(ref int count); 
     [PreserveSig] 
     int SetCurrentPreset(int currentpreset); 
     [PreserveSig] 
     int GetCurrentPreset(ref int currentpreset); 
     [PreserveSig] 
     int DisplayPropertyPage(IntPtr hwndOwner); 
     [PreserveSig] 
     int GoFullScreen(bool fFullscreen); 
     [PreserveSig] 
     int RenderFullScreen(ref TimedLevel pLevels); 
    } 


    //[ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct Data 
    { 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] 
     public byte[] Data0; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] 
     public byte[] Data1; 
    } 

    //[ComVisible(true)] 
    public enum PlayerState 
    { 
     Stop_State, 
     Pause_State, 
     Play_State 
    } 

    //[ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct TimedLevel 
    { 
     public Data Frequency; 
     public Data Waveform; 
     public PlayerState State; 
     public long TimeStamp; 
    } 

    //[ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
     public int Width { get { return this.Right - this.Left; } } 
     public int Height { get { return this.Bottom - this.Top; } } 
    } 
} 
Cuestiones relacionadas