2010-01-13 13 views
5

Sto tentando di creare un plug-in di visualizzazione di Windows Media Player (WMP) in C#. Sono abbastanza nuovo nell'esporre C# a COM e potrebbe essermi perso qualcosa di base. Ho insistito con questo per 3 giorni (circa 20 ore) e non ho superato il singolo problema che descriverò di seguito.C# Com Interop con visualizzazione di Windows Media Player (con codice di esempio)

Per chi non lo sapesse, le visualizzazioni WMP sono le immagini graziose che vengono visualizzate nel lettore multimediale durante l'ascolto della musica.

In breve: WMP chiamerà determinati metodi nell'interfaccia COM C#, ma non in altri.

ho installato WMP 11

ho scaricato l'ultima Windows SDK che contiene una procedura guidata C++ plugin per compilare un campione di visualizzazione di lavoro. Questo esempio registra e funziona senza problemi in WMP.

Il kit di sviluppo contiene un file di intestazione C++ denominato effects.h che contiene 2 interfacce che devono essere implementate per far funzionare il plugin con WMP. Non sembra molto più complicato di così.

Eccoli

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; 

}; 

Come ho detto, la mia conoscenza COM non il mio essere il migliore. Questo è quello che ho fatto per portarlo su C#.

ho convertito le interfacce a seguire

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; 
    } 
} 

Il codice per la classe che implementa le interfacce è la seguente

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; 

    } 

Come si può vedere il mio codice è abbastanza vuoto, niente di più che stub davvero . Il mio debug è semplice ma fa il lavoro.

Una volta che questo è compilato con un nome sicuro può essere registrato con:

regasm assemblyname.dll/tlb

poi caduto nel GAC.

Aprire regedit e aggiungere il seguente informazioni:

Sotto HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ MediaPlayer \ Objects \ Effetti

Nuova chiave: WmpTestPlugin

Sotto la nuova chiave aggiunge una nuova stringa valore: Nome: classid Valore: {C47 6FF24-5E5C-419d-9110-05EC2EED8511}

Così abbiamo costruito un plugin che è conforme alle interfacce, ha registrato nel GAC e ha detto ai media player è lì.

Se si apre il lettore multimediale e si fa clic con il tasto destro sullo spazio di visualizzazione, viene visualizzato un menu. In quel menu sarà il nostro nuovo plugin.Quando si sposta il mouse sul nuovo elemento, WMP chiamerà GetPresetCount sul plug-in (ciò accederà al file). Quindi WMP dovrebbe chiamare GetPresetTitle ma non lo fa MAI per me.

Se si aprono gli strumenti \ opzioni dalla barra dei menu e si seleziona la scheda Plugin, è possibile selezionare il nuovo plug-in. Se si fa clic su Proprietà, WMP chiamerà GetCapabilities quindi DisplayPropertyPage e verrà visualizzata una finestra di messaggio dal plug-in. WMP quindi si blocca. Nella versione C++ FinalConstruct() viene chiamata nell'interfaccia CComCoClass - Non ce l'ho e non so cosa sia. Penso che potrebbe essere più basso di quello che sto usando ??

Ho provato molte cose per far funzionare tutto ciò, incluso il cambio delle dichiarazioni dei metodi. Per favore qualcuno può guardarlo e aiutare. Ho cercato sul web una soluzione e non ho trovato nulla.

Grazie per la lettura, Nanook

+0

Per testare questo un po 'più ho creato un'applicazione VB6 (COM) se mi riferisco la mia C# plugin e il C++ (di lavoro) plug-in che può chiamare ** GetPresetCount ** quindi ** GetPresetTitle ** e ricevere il mio testo indietro senza problemi. Questo almeno mi dice che i tipi di riferimento sono corretti, ma non che l'interfaccia sia accurata al 100% o che COM sia configurata correttamente per WMP per vederlo. – Nanook

+0

Per favore qualcuno può provarlo. Oppure vota come una buona domanda. – Nanook

risposta

6

Dopo aver guardato un po 'di codice di interoperabilità shell di Windows ho scoperto che avrei dovuto usando [ComImport] e NON [ComVisible] per le interfacce. Per rendere le firme uguali a quelle già registrate ho usato [PreserveSig]. Anche l'ereditarietà dell'interfaccia aveva bisogno di aiuto ridichiando l'interfaccia di base all'interno del genitore.

Spero che questo aiuti qualcuno.

Ecco la classe operaia

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; } } 
    } 
} 
Problemi correlati