更改主音量级别

问题描述 投票:14回答:3

如何更改主音量级别?使用此代码

[DllImport ("winmm.dll")]
public static extern int waveOutSetVolume (IntPtr hwo, uint dwVolume);

waveOutSetVolume (IntPtr.Zero, (((uint)uint.MaxValue & 0x0000ffff) | ((uint)uint.MaxValue << 16)));

我可以设置波形音量,但是如果主音量太低,则不会产生任何效果。

感谢您的帮助。

c# winapi volume
3个回答
30
投票

好,去了:

const int MAXPNAMELEN            = 32;
const int MIXER_SHORT_NAME_CHARS = 16;
const int MIXER_LONG_NAME_CHARS  = 64;

[Flags] enum MIXERLINE_LINEF : uint{
    ACTIVE       = 0x00000001,
    DISCONNECTED = 0x00008000,
    SOURCE       = 0x80000000
}
[Flags] enum MIXER           : uint{
    GETLINEINFOF_DESTINATION     = 0x00000000,
    GETLINEINFOF_SOURCE          = 0x00000001,
    GETLINEINFOF_LINEID          = 0x00000002,
    GETLINEINFOF_COMPONENTTYPE   = 0x00000003,
    GETLINEINFOF_TARGETTYPE      = 0x00000004,
    GETLINEINFOF_QUERYMASK       = 0x0000000F,

    GETLINECONTROLSF_ALL         = 0x00000000,
    GETLINECONTROLSF_ONEBYID     = 0x00000001,
    GETLINECONTROLSF_ONEBYTYPE   = 0x00000002,
    GETLINECONTROLSF_QUERYMASK   = 0x0000000F,

    GETCONTROLDETAILSF_VALUE     = 0x00000000,
    GETCONTROLDETAILSF_LISTTEXT  = 0x00000001,
    GETCONTROLDETAILSF_QUERYMASK = 0x0000000F,

    OBJECTF_MIXER                = 0x00000000,
    OBJECTF_WAVEOUT              = 0x10000000,
    OBJECTF_WAVEIN               = 0x20000000,
    OBJECTF_MIDIOUT              = 0x30000000,
    OBJECTF_MIDIIN               = 0x40000000,
    OBJECTF_AUX                  = 0x50000000,
    OBJECTF_HANDLE               = 0x80000000,
    OBJECTF_HMIXER               = OBJECTF_HANDLE | OBJECTF_MIXER,
    OBJECTF_HWAVEOUT             = OBJECTF_HANDLE | OBJECTF_WAVEOUT,
    OBJECTF_HWAVEIN              = OBJECTF_HANDLE | OBJECTF_WAVEIN,
    OBJECTF_HMIDIOUT             = OBJECTF_HANDLE | OBJECTF_MIDIOUT,
    OBJECTF_HMIDIIN              = OBJECTF_HANDLE | OBJECTF_MIDIIN
}
[Flags] enum MIXERCONTROL_CT : uint{
    CLASS_MASK        = 0xF0000000,
    CLASS_CUSTOM      = 0x00000000,
    CLASS_METER       = 0x10000000,
    CLASS_SWITCH      = 0x20000000,
    CLASS_NUMBER      = 0x30000000,
    CLASS_SLIDER      = 0x40000000,
    CLASS_FADER       = 0x50000000,
    CLASS_TIME        = 0x60000000,
    CLASS_LIST        = 0x70000000,

    SUBCLASS_MASK     = 0x0F000000,

    SC_SWITCH_BOOLEAN = 0x00000000,
    SC_SWITCH_BUTTON  = 0x01000000,

    SC_METER_POLLED   = 0x00000000,

    SC_TIME_MICROSECS = 0x00000000,
    SC_TIME_MILLISECS = 0x01000000,

    SC_LIST_SINGLE    = 0x00000000,
    SC_LIST_MULTIPLE  = 0x01000000,

    UNITS_MASK        = 0x00FF0000,
    UNITS_CUSTOM      = 0x00000000,
    UNITS_BOOLEAN     = 0x00010000,
    UNITS_SIGNED      = 0x00020000,
    UNITS_UNSIGNED    = 0x00030000,
    UNITS_DECIBELS    = 0x00040000, /* in 10ths */
    UNITS_PERCENT     = 0x00050000, /* in 10ths */
}
[Flags] enum MIXERCONTROL_CONTROLTYPE : uint{
    CUSTOM         = MIXERCONTROL_CT.CLASS_CUSTOM | MIXERCONTROL_CT.UNITS_CUSTOM,
    BOOLEANMETER   = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_BOOLEAN,
    SIGNEDMETER    = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_SIGNED,
    PEAKMETER      = SIGNEDMETER + 1,
    UNSIGNEDMETER  = MIXERCONTROL_CT.CLASS_METER | MIXERCONTROL_CT.SC_METER_POLLED | MIXERCONTROL_CT.UNITS_UNSIGNED,
    BOOLEAN        = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BOOLEAN | MIXERCONTROL_CT.UNITS_BOOLEAN,
    ONOFF          = BOOLEAN + 1,
    MUTE           = BOOLEAN + 2,
    MONO           = BOOLEAN + 3,
    LOUDNESS       = BOOLEAN + 4,
    STEREOENH      = BOOLEAN + 5,
    BASS_BOOST     = BOOLEAN + 0x00002277,
    BUTTON         = MIXERCONTROL_CT.CLASS_SWITCH | MIXERCONTROL_CT.SC_SWITCH_BUTTON | MIXERCONTROL_CT.UNITS_BOOLEAN,
    DECIBELS       = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_DECIBELS,
    SIGNED         = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_SIGNED,
    UNSIGNED       = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_UNSIGNED,
    PERCENT        = MIXERCONTROL_CT.CLASS_NUMBER | MIXERCONTROL_CT.UNITS_PERCENT,
    SLIDER         = MIXERCONTROL_CT.CLASS_SLIDER | MIXERCONTROL_CT.UNITS_SIGNED,
    PAN            = SLIDER + 1,
    QSOUNDPAN      = SLIDER + 2,
    FADER          = MIXERCONTROL_CT.CLASS_FADER | MIXERCONTROL_CT.UNITS_UNSIGNED,
    VOLUME         = FADER + 1,
    BASS           = FADER + 2,
    TREBLE         = FADER + 3,
    EQUALIZER      = FADER + 4,
    SINGLESELECT   = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_SINGLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
    MUX            = SINGLESELECT + 1,
    MULTIPLESELECT = MIXERCONTROL_CT.CLASS_LIST | MIXERCONTROL_CT.SC_LIST_MULTIPLE | MIXERCONTROL_CT.UNITS_BOOLEAN,
    MIXER          = MULTIPLESELECT + 1,
    MICROTIME      = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MICROSECS | MIXERCONTROL_CT.UNITS_UNSIGNED,
    MILLITIME      = MIXERCONTROL_CT.CLASS_TIME | MIXERCONTROL_CT.SC_TIME_MILLISECS | MIXERCONTROL_CT.UNITS_UNSIGNED
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct MIXERLINE{
    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
    public struct TargetInfo{
        public uint   dwType;
        public uint   dwDeviceID;
        public ushort wMid;
        public ushort wPid;
        public uint   vDriverVersion;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAXPNAMELEN)]
        public string szPname;
    }

    public uint            cbStruct;
    public uint            dwDestination;
    public uint            dwSource;
    public uint            dwLineID;
    public MIXERLINE_LINEF fdwLine;
    public uint            dwUser;
    public uint            dwComponentType;
    public uint            cChannels;
    public uint            cConnection;
    public uint            cControls;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_SHORT_NAME_CHARS)]
    public string          szShortName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_LONG_NAME_CHARS)]
    public string          szName;
    public TargetInfo      Target;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct MIXERCONTROL{
    [StructLayout(LayoutKind.Explicit)]
    public struct BoundsInfo{
        [FieldOffset(0)]
        public int    lMinimum;
        [FieldOffset(4)]
        public int    lMaximum;
        [FieldOffset(0)]
        public uint   dwMinimum;
        [FieldOffset(4)]
        public uint   dwMaximum;
        [FieldOffset(8), MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
        public uint[] dwReserved;
    }
    [StructLayout(LayoutKind.Explicit)]
    public struct MetricsInfo{
        [FieldOffset(0)]
        public uint   cSteps;
        [FieldOffset(0)]
        public uint   cbCustomData;
        [FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst=5)]
        public uint[] dwReserved;
    }

    public uint                     cbStruct;
    public uint                     dwControlID;
    public MIXERCONTROL_CONTROLTYPE dwControlType;
    public uint                     fdwControl;
    public uint                     cMultipleItems;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_SHORT_NAME_CHARS)]
    public string                   szShortName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MIXER_LONG_NAME_CHARS)]
    public string                   szName;
    public BoundsInfo               Bounds;
    public MetricsInfo              Metrics;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERLINECONTROLS{
    [FieldOffset(0)]
    public uint   cbStruct;
    [FieldOffset(4)]
    public uint   dwLineID;
    [FieldOffset(8)]
    public uint   dwControlID;
    [FieldOffset(8)] // not a typo!  overlaps previous field
    public uint   dwControlType;
    [FieldOffset(12)]
    public uint   cControls;
    [FieldOffset(16)]
    public uint   cbmxctrl;
    [FieldOffset(20)]
    public IntPtr pamxctrl;
}
[StructLayout(LayoutKind.Explicit)]
struct MIXERCONTROLDETAILS{
    [FieldOffset(0)]
    public uint   cbStruct;
    [FieldOffset(4)]
    public uint   dwControlID;
    [FieldOffset(8)]
    public uint   cChannels;
    [FieldOffset(12)]
    public IntPtr hwndOwner;
    [FieldOffset(12)] // not a typo!
    public uint   cMultipleItems;
    [FieldOffset(16)]
    public uint   cbDetails;
    [FieldOffset(20)]
    public IntPtr paDetails;
}
[StructLayout(LayoutKind.Sequential)]
struct VOLUME{
    public int left;
    public int right;
}
struct MixerInfo{
    public uint volumeCtl;
    public uint muteCtl;
    public int  minVolume;
    public int  maxVolume;
}

[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetLineInfo      (IntPtr hmxobj, ref MIXERLINE pmxl, MIXER flags);

[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetLineControls  (IntPtr hmxobj, ref MIXERLINECONTROLS pmxlc, MIXER flags);

[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerGetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);

[DllImport("WinMM.dll", CharSet=CharSet.Auto)]
static extern uint mixerSetControlDetails(IntPtr hmxobj, ref MIXERCONTROLDETAILS pmxcd, MIXER flags);

static MixerInfo GetMixerControls(){
    MIXERLINE         mxl = new MIXERLINE();
    MIXERLINECONTROLS mlc = new MIXERLINECONTROLS();
    mxl.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINE));
    mlc.cbStruct = (uint)Marshal.SizeOf(typeof(MIXERLINECONTROLS));

    mixerGetLineInfo(IntPtr.Zero, ref mxl, MIXER.OBJECTF_MIXER | MIXER.GETLINEINFOF_DESTINATION);

    mlc.dwLineID  = mxl.dwLineID;
    mlc.cControls = mxl.cControls;
    mlc.cbmxctrl  = (uint)Marshal.SizeOf(typeof(MIXERCONTROL));
    mlc.pamxctrl  = Marshal.AllocHGlobal((int)(mlc.cbmxctrl * mlc.cControls));

    mixerGetLineControls(IntPtr.Zero, ref mlc, MIXER.OBJECTF_MIXER | MIXER.GETLINECONTROLSF_ALL);

    MixerInfo rtn = new MixerInfo();

    for(int i = 0; i < mlc.cControls; i++){
        MIXERCONTROL mxc = (MIXERCONTROL)Marshal.PtrToStructure((IntPtr)((int)mlc.pamxctrl + (int)mlc.cbmxctrl * i), typeof(MIXERCONTROL));
        switch(mxc.dwControlType){
        case MIXERCONTROL_CONTROLTYPE.VOLUME:
            rtn.volumeCtl = mxc.dwControlID;
            rtn.minVolume = mxc.Bounds.lMinimum;
            rtn.maxVolume = mxc.Bounds.lMaximum;
            break;
        case MIXERCONTROL_CONTROLTYPE.MUTE:
            rtn.muteCtl = mxc.dwControlID;
            break;
        }
    }

    Marshal.FreeHGlobal(mlc.pamxctrl);

    return rtn;
}
static VOLUME GetVolume(MixerInfo mi){
    MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
    mcd.cbStruct       = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
    mcd.dwControlID    = mi.volumeCtl;
    mcd.cMultipleItems = 0;
    mcd.cChannels      = 2;
    mcd.cbDetails      = (uint)Marshal.SizeOf(typeof(int));
    mcd.paDetails      = Marshal.AllocHGlobal((int)mcd.cbDetails);

    mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

    VOLUME rtn = (VOLUME)Marshal.PtrToStructure(mcd.paDetails, typeof(VOLUME));

    Marshal.FreeHGlobal(mcd.paDetails);

    return rtn;
}
static bool IsMuted(MixerInfo mi){
    MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
    mcd.cbStruct       = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
    mcd.dwControlID    = mi.muteCtl;
    mcd.cMultipleItems = 0;
    mcd.cChannels      = 1;
    mcd.cbDetails      = 4;
    mcd.paDetails      = Marshal.AllocHGlobal((int)mcd.cbDetails);

    mixerGetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

    int rtn = Marshal.ReadInt32(mcd.paDetails);

    Marshal.FreeHGlobal(mcd.paDetails);

    return rtn != 0;
}
static void AdjustVolume(MixerInfo mi, int delta){
    VOLUME volume = GetVolume(mi);

    if(delta > 0){
        volume.left  = Math.Min(mi.maxVolume, volume.left  + delta);
        volume.right = Math.Min(mi.maxVolume, volume.right + delta);
    }else{
        volume.left  = Math.Max(mi.minVolume, volume.left  + delta);
        volume.right = Math.Max(mi.minVolume, volume.right + delta);
    }

    SetVolume(mi, volume);
}
static void SetVolume(MixerInfo mi, VOLUME volume){
    MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
    mcd.cbStruct       = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
    mcd.dwControlID    = mi.volumeCtl;
    mcd.cMultipleItems = 0;
    mcd.cChannels      = 2;
    mcd.cbDetails      = (uint)Marshal.SizeOf(typeof(int));
    mcd.paDetails      = Marshal.AllocHGlobal((int)mcd.cbDetails);

    Marshal.StructureToPtr(volume, mcd.paDetails, false);

    mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

    Marshal.FreeHGlobal(mcd.paDetails);
}
static void SetMute(MixerInfo mi, bool mute){
    MIXERCONTROLDETAILS mcd = new MIXERCONTROLDETAILS();
    mcd.cbStruct       = (uint)Marshal.SizeOf(typeof(MIXERCONTROLDETAILS));
    mcd.dwControlID    = mi.muteCtl;
    mcd.cMultipleItems = 0;
    mcd.cChannels      = 1;
    mcd.cbDetails      = 4;
    mcd.paDetails      = Marshal.AllocHGlobal((int)mcd.cbDetails);

    Marshal.WriteInt32(mcd.paDetails, mute ? 1 : 0);

    mixerSetControlDetails(IntPtr.Zero, ref mcd, MIXER.GETCONTROLDETAILSF_VALUE | MIXER.OBJECTF_MIXER);

    Marshal.FreeHGlobal(mcd.paDetails);
}

此代码庞大而丑陋。它是对某些C ++代码的翻译,并且由于必须定义所有P / Invoke内容,因此代码很多。但我已经对其进行了测试,并且可以正常工作。要使用它,您只需要类似:

MixerInfo mi = GetMixerControls();
AdjustVolume(mi, 100);    // add 100 to the current volume

MixerInfo mi = GetMixerControls();
AdjustVolume(mi, (mi.maxVolume - mi.minVolume) / 10);    // increase the volume by 10% of total range

MixerInfo mi = GetMixerControls();
SetVolume(mi, mi.maxVolume);    // let's get this party crunk'd!

MixerInfo mi = GetMixerControls();
SetMute(mi, true);    // shhhh!!!!!!

警告

由于使用固定大小的int和字段偏移量,在64位Windows上,这可能会失败。我不知道,我还没有测试过,也没有足够的注意力来知道这些字段的大小是否扩展到64位。 caveat codor

编辑

为了简单起见(相对而言),我省略了任何错误处理。您实际上应该检查所有mixerXXX函数的返回码,但我将其留给读者练习(阅读为:我懒得这么做)。


6
投票

对于主卷(对于Vista及更高版本,应为:

ISimpleAudioVolume::SetMasterVolume

here中所述,您可以参考以下部分:

Core Audio APIs in Windows Vista了解更多。

此呼叫不是Media Foundation呼叫,而是WASAPI(Windows音频会话API)呼叫:ISimpleAudioVolume :: SetMasterVolume(SetMasterVolume方法设置音频会话的主音量级别。)

然而,要使Media Center的UI反映该调用设置的新声音级别(如thread illustrates那样,这可能很难。

对于Windows XP,您可以研究此script,也可以研究this other scriptAudio Library可能也很有趣。

还有这个旧的Audio Project,其中有一个主音量部分:

BOOL CVolumeDlg::amdInitialize()
{
    ASSERT(m_hMixer == NULL);

    // get the number of mixer devices present in the system
    m_nNumMixers = ::mixerGetNumDevs();

    m_hMixer = NULL;
    ::ZeroMemory(&m_mxcaps, sizeof(MIXERCAPS));

    m_strDstLineName.Empty();
    m_strVolumeControlName.Empty();
    m_dwMinimum = 0;
    m_dwMaximum = 0;
    m_dwVolumeControlID = 0;

    // open the first mixer
    // A "mapper" for audio mixer devices does not currently exist.
    if (m_nNumMixers != 0)
    {
        if (::mixerOpen(&m_hMixer,
                        0,
                        reinterpret_cast<DWORD>(this->GetSafeHwnd()),
                        NULL,
                        MIXER_OBJECTF_MIXER | CALLBACK_WINDOW)
            != MMSYSERR_NOERROR)
        {
            return FALSE;
        }

        if (::mixerGetDevCaps(reinterpret_cast<UINT>(m_hMixer),
                              &m_mxcaps, sizeof(MIXERCAPS))
            != MMSYSERR_NOERROR)
        {
            return FALSE;
        }
    }

    return TRUE;
}

BOOL CVolumeDlg::amdUninitialize()
{
    BOOL bSucc = TRUE;

    if (m_hMixer != NULL)
    {
        bSucc = (::mixerClose(m_hMixer) == MMSYSERR_NOERROR);
        m_hMixer = NULL;
    }

    return bSucc;
}

BOOL CVolumeDlg::amdGetMasterVolumeControl()
{
    if (m_hMixer == NULL)
    {
        return FALSE;
    }

    // get dwLineID
    MIXERLINE mxl;
    mxl.cbStruct = sizeof(MIXERLINE);
    mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
    if (::mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(m_hMixer),
                           &mxl,
                           MIXER_OBJECTF_HMIXER |
                           MIXER_GETLINEINFOF_COMPONENTTYPE)
        != MMSYSERR_NOERROR)
    {
        return FALSE;
    }

    // get dwControlID
    MIXERCONTROL mxc;
    MIXERLINECONTROLS mxlc;
    mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
    mxlc.dwLineID = mxl.dwLineID;
    mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
    mxlc.cControls = 1;
    mxlc.cbmxctrl = sizeof(MIXERCONTROL);
    mxlc.pamxctrl = &mxc;
    if (::mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(m_hMixer),
                               &mxlc,
                               MIXER_OBJECTF_HMIXER |
                               MIXER_GETLINECONTROLSF_ONEBYTYPE)
        != MMSYSERR_NOERROR)
    {
        return FALSE;
    }

    // store dwControlID
    m_strDstLineName = mxl.szName;
    m_strVolumeControlName = mxc.szName;
    m_dwMinimum = mxc.Bounds.dwMinimum;
    m_dwMaximum = mxc.Bounds.dwMaximum;
    m_dwVolumeControlID = mxc.dwControlID;

    return TRUE;
}

BOOL CVolumeDlg::amdGetMasterVolumeValue(DWORD &dwVal) const
{
    if (m_hMixer == NULL)
    {
        return FALSE;
    }

    MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
    MIXERCONTROLDETAILS mxcd;
    mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
    mxcd.dwControlID = m_dwVolumeControlID;
    mxcd.cChannels = 1;
    mxcd.cMultipleItems = 0;
    mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
    mxcd.paDetails = &mxcdVolume;
    if (::mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(m_hMixer),
                                 &mxcd,
                                 MIXER_OBJECTF_HMIXER |
                                 MIXER_GETCONTROLDETAILSF_VALUE)
        != MMSYSERR_NOERROR)
    {
        return FALSE;
    }

    dwVal = mxcdVolume.dwValue;

    return TRUE;
}

BOOL CVolumeDlg::amdSetMasterVolumeValue(DWORD dwVal) const
{
    if (m_hMixer == NULL)
    {
        return FALSE;
    }

    MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = { dwVal };
    MIXERCONTROLDETAILS mxcd;
    mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
    mxcd.dwControlID = m_dwVolumeControlID;
    mxcd.cChannels = 1;
    mxcd.cMultipleItems = 0;
    mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
    mxcd.paDetails = &mxcdVolume;
    if (::mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(m_hMixer),
                                 &mxcd,
                                 MIXER_OBJECTF_HMIXER |
                                 MIXER_SETCONTROLDETAILSF_VALUE)
        != MMSYSERR_NOERROR)
    {
        return FALSE;
    }

    return TRUE;
}

-1
投票

使用这个免费的库,很简单,就可以了。InputSimulator

它模拟按键。您只需要添加此引用并在需要此类静态方法的任何地方调用:

  InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_UP);

  InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_DOWN);

  InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_MUTE);

然后,如果您想获得主vokume级别,请执行以下操作:

  // volume update
  MMDevice defaultDevice = new MMDeviceEnumerator()
        .GetDefaultAudioEndpoint(DataFlow.Render‌​, Role.Multimedia);
  // veloce attesa per l'aggiornamento del volume
  Thread.Sleep(100);
  float level = defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar; 

这样做,您可以将当前音量调整为0-1格式(例如52%为0.52)。如果您想要将其调整为0-100格式,只需执行level * 100

© www.soinside.com 2019 - 2024. All rights reserved.