简体   繁体   English

C#Com Interop与Windows Media Player可视化(带有示例代码)

[英]C# Com Interop with Windows Media Player Visualisation (With Sample Code)

I am attempting to create a Windows Media Player (WMP) Visualization plugin in C#. 我正在尝试在C#中创建Windows Media Player(WMP)可视化插件。 I am quite new to exposing C# to COM and may have missed something basic. 我对将C#暴露给COM还是很陌生,可能已经错过了一些基本知识。 I have persisted with this for 3 days (about 20 hours) and not got past the single issue I will describe below. 我已经坚持了3天(大约20个小时),但没有超过我将在下面描述的单个问题。

For those who don't know, WMP visualizations are the pretty images that show in media player while listening to music. 对于那些不知道的人,WMP可视化效果是在听音乐时在媒体播放器中显示的漂亮图像。

In a nutshell : WMP will call certain methods on my C# COM interface, but not others. 简而言之 :WMP将在我的C#COM接口上调用某些方法,但不会调用其他方法。

I have WMP 11 installed 我已安装WMP 11

I downloaded the Latest Windows SDK which contains a C++ plugin wizard to compile a working visualization sample. 我下载了最新的Windows SDK ,其中包含一个C ++插件向导,用于编译有效的可视化示例。 This sample registers and works without issues in WMP. 此示例注册并在WMP中正常工作。

The dev kit contains a C++ header file named effects.h that contains 2 interfaces that must be implemented to get the plugin to work with WMP. 开发套件包含一个名为effects.h的C ++头文件,该文件包含两个接口,必须实现这些接口才能使该插件与WMP一起使用。 It doesn't appear to much more complicated than that. 似乎没有那么复杂。

Here they are 他们来了

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;

};

As I mentioned, my COM knowledge my not be the best. 如前所述,我的COM知识不是最好的。 This is what I did to port it to C#. 这就是我将其移植到C#的过程。

I converted the interfaces to following 我将接口转换为以下

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

The code for the class implementing the interfaces is as follows 实现接口的类的代码如下

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;

    }

As you can see my code is pretty empty, nothing more than stubs really. 如您所见,我的代码非常空,实际上只是存根。 My debugging is simple but does the job. 我的调试很简单,但是可以完成工作。

Once this is compiled with a strong name it can be registered with: 使用强名编译后,可以在以下位置注册:

regasm assemblyname.dll /tlb regasm assemblyname.dll / tlb

then dropped in the gac. 然后掉进了gac。

Open regedit and add the the following info: 打开regedit并添加以下信息:

Under HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MediaPlayer\\Objects\\Effects HKEY_LOCAL_MACHINE \\ SOFTWARE \\ Microsoft \\ MediaPlayer \\ Objects \\ Effects下

New Key: WmpTestPlugin 新密钥: WmpTestPlugin

Under the new key add a new string value: Name: classid Value: {C476FF24-5E5C-419d-9110-05EC2EED8511} 在新密钥下添加新的字符串值:名称:classid值:{C476FF24-5E5C-419d-9110-05EC2EED8511}

So we have built a plugin that conforms to the interfaces, registered it in the GAC and told media player it's there. 因此,我们构建了一个符合接口的插件,并在GAC中注册了插件,并告诉媒体播放器它已经在那。

If you open media player and right-click on the visualization space a menu will appear. 如果打开媒体播放器并右键单击可视化空间,将出现一个菜单。 In that menu will be our new plugin. 在该菜单中将是我们的新插件。 When you move your mouse down to the new item WMP will call GetPresetCount on the plugin (this will log to the file). 当您将鼠标移到新项目时,WMP将在插件上调用GetPresetCount (这将记录到文件中)。 Then WMP is supposed to call GetPresetTitle but it NEVER does for me. 然后,WMP应该调用GetPresetTitle,但它永远不会为我做。

If you open tools\\options from the menu bar and select the Plugins tab you can select the new plugin. 如果从菜单栏中打开工具\\选项,然后选择插件选项卡,则可以选择新插件。 If you click Properties WMP will call GetCapabilities then DisplayPropertyPage and a message box from the plugin will appear. 如果单击“属性”,则WMP将调用GetCapabilities,然后将显示DisplayPropertyPage和来自插件的消息框。 WMP then crashes. 然后WMP崩溃。 In the C++ version FinalConstruct() is called on a CComCoClass interface - I don't have this and don't know what it is. 在C ++版本中,在CComCoClass接口上调用了FinalConstruct() -我没有这个,也不知道它是什么。 I think it may be lower level than I am using?? 我认为它可能比我正在使用的水平低?

I have tried many many things to get this to work including changing the method declarations. 我已经尝试了很多方法来使它起作用,包括更改方法声明。 Please can someone look at it and help. 请有人看一下并提供帮助。 I've looked all over the web for a solution and found nothing. 我在网上寻找解决方案,却一无所获。

Thanks for reading, Nanook 感谢您的阅读,Nanook

After looking at some Windows Shell interop code I discovered that I should have been using [ComImport] and NOT [ComVisible] for the interfaces. 查看一些Windows Shell互操作代码后,我发现我应该一直在使用[ComImport]而不是[ComVisible]作为接口。 To make the signatures equal to that already registered I used [PreserveSig]. 为了使签名等于已注册的签名,我使用了[PreserveSig]。 The interface inheritence also needed some help by redeclaring the base interface within the parent. 通过在父级中重新声明基本接口,接口继承也需要一些帮助。

I hope this helps someone. 我希望这可以帮助别人。

Here is the working class 这是工人阶级

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM