使用C#设置Windows卷

时间:2016-04-14 14:04:45

标签: c# windows volume

我一直在网上搜索从C#控制电脑音频的方法。我发现这段代码工作正常。

    public static float GetMasterVolume()
    {
        // get the speakers (1st render + multimedia) device
        IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
        IMMDevice speakers;
        const int eRender = 0;
        const int eMultimedia = 1;
        deviceEnumerator.GetDefaultAudioEndpoint(eRender, eMultimedia, out speakers);

        object o;
        speakers.Activate(typeof(IAudioEndpointVolume).GUID, 0, IntPtr.Zero, out o);
        IAudioEndpointVolume aepv = (IAudioEndpointVolume)o;
        float volume = aepv.GetMasterVolumeLevelScalar();
        Marshal.ReleaseComObject(aepv);
        Marshal.ReleaseComObject(speakers);
        Marshal.ReleaseComObject(deviceEnumerator);
        return volume;
    }

    [ComImport]
    [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
    private class MMDeviceEnumerator
    {
    }

    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IAudioEndpointVolume
    {
        void _VtblGap1_6();
        float GetMasterVolumeLevelScalar();
    }

    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IMMDeviceEnumerator
    {
        void _VtblGap1_1();

        [PreserveSig]
        int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice);
    }

    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IMMDevice
    {
        [PreserveSig]
        int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
    }

这是getVolume函数。我认为必须采用类似的方式设置音量。我遇到了这种方法:

SetMasterVolumeLevelScalar()

HRESULT SetMasterVolumeLevelScalar(
  [in] float   fLevel,
  [in] LPCGUID pguidEventContext
);

但我无法理解第二个参数。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

我发现你已经解决了这个问题,但是想为其他好奇或需要帮助的人提供正式答案。

当您致电SetMasterVolumeLevelScalar时,您将百分比从0.0传递到1.0并传入GUID。你也可以传入Null;然而。传递GUID的原因是任何其他应用程序更改都可以检查更改并查看它是否是他们或其他应用程序。例如:

如果您注册OnNotify进行音量更改,则每次音量更改时都会收到一个结构。结构中的第一个字段是GUID。如果你传入一个常量GUID来改变音量,那么这个结构将显示你自己的GUID;你可以比较它,忽略它或其他什么。如果结构传递的是NULL或不同的GUID,那么您知道另一个应用程序已经更改了卷,并且您可能希望在此时执行不同的操作。

希望这会有所帮助:)

答案 1 :(得分:0)

定义您的界面......

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioEndpointVolume
{
    // ...
    Int32 GetMasterVolumeLevelScalar(ref Single pfLevel);
    Int32 SetMasterVolumeLevelScalar(Single fLevel, Guid pguidEventContext);
    // ...
}

然后,在你的课堂上,例如:

public class EndpointVolume
{
    private readonly Guid m_GuidEventContext;
    private IAudioEndpointVolume m_AudioEndpoint;

    public EndpointVolume()
    {
        m_GuidEventContext = Guid.NewGuid();
        m_AudioEndpoint = ...
    }

    public Single MasterVolume
    {
        get
        {
            Single level = 0.0f;
            Int32 res = m_AudioEndpoint.GetMasterVolumeLevelScalar(ref level);

            if (retVal != 0)
                throw new Exception("AudioEndpointVolume.GetMasterVolumeLevelScalar()");

            return level;
        }

        set
        {
            Single level = value;

            if (level < 0.0f)
                level = 0.0f;
            else if (level > 1.0f)
                level = 0.0f;

            Int32 res = m_AudioEndpoint.SetMasterVolumeLevelScalar(level, m_GuidEventContext);

            if (res!= 0)
                throw new Exception("AudioEndpointVolume.SetMasterVolumeLevelScalar()");
        }
    }

    // ...
}

pguidEventContext参数用于定义当前事件上下文,以便对主卷所做的更改将反映到所有其他客户端。来自official documentation

  

IAudioEndpointVolumeCallback :: OnNotify方法的上下文值。   此参数指向事件上下文GUID。如果   SetMasterVolumeLevelScalar调用更改了音量级别   端点,已注册的所有客户端   与该端点的IAudioEndpointVolumeCallback接口将   收到通知。在其OnNotify方法的实现中,a   客户端可以检查事件上下文GUID以发现它是否   另一个客户端是音量变化事件的来源。如果是来电者   为此参数提供NULL指针,即通知例程   接收上下文GUID值GUID_NULL。