C# 更改主音量级别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/294292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Changing master volume level
提问by lacop
How can I change the master volume level? Using this code
如何更改主音量级别?使用此代码
[DllImport ("winmm.dll")]
public static extern int waveOutSetVolume (IntPtr hwo, uint dwVolume);
waveOutSetVolume (IntPtr.Zero, (((uint)uint.MaxValue & 0x0000ffff) | ((uint)uint.MaxValue << 16)));
I can set the wave volume but if the master volume is too low this won't have any effect.
我可以设置波形音量,但如果主音量太低,这不会有任何影响。
Thanks for any help.
谢谢你的帮助。
采纳答案by P Daddy
Okay, here goes:
好的,下面开始:
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);
}
This code is huge and ugly. It's a translation of some C++ code, and with having to define all the P/Invoke stuff, it's a lot more code. But I've tested it, and it works. To use it, you simply need something like:
这段代码又大又丑。它是一些 C++ 代码的翻译,并且必须定义所有 P/Invoke 内容,因此代码要多得多。但我已经测试过了,它有效。要使用它,你只需要像这样:
MixerInfo mi = GetMixerControls();
AdjustVolume(mi, 100); // add 100 to the current volume
or
或者
MixerInfo mi = GetMixerControls();
AdjustVolume(mi, (mi.maxVolume - mi.minVolume) / 10); // increase the volume by 10% of total range
or
或者
MixerInfo mi = GetMixerControls();
SetVolume(mi, mi.maxVolume); // let's get this party crunk'd!
or
或者
MixerInfo mi = GetMixerControls();
SetMute(mi, true); // shhhh!!!!!!
WARNING
警告
Due to the use of fixed-sized ints and field offsets, this may fail fantastically on 64-bit Windows. I don't know, I haven't tested it and haven't paid enough attention to know if these field sizes expand to 64 bits. caveat codor
由于使用固定大小的整数和字段偏移量,这在 64 位 Windows 上可能会非常失败。我不知道,我没有测试过,也没有足够关注知道这些字段大小是否扩展到 64 位。 警告性气味
EDIT
编辑
For the sake of simplicity (relatively speaking), I've left out any error handling. You should really check the return codes of all the mixerXXX functions, but I'll leave that as an exercise for the reader (read as: I was too lazy to do this).
为了简单起见(相对而言),我省略了任何错误处理。您真的应该检查所有mixerXXX 函数的返回码,但我将把它留给读者作为练习(读作:我懒得这样做)。
回答by VonC
For the master volume (for Vista and above), that would be:
对于主卷(对于 Vista 及更高版本),这将是:
ISimpleAudioVolume::SetMasterVolume
ISimpleAudioVolume::SetMasterVolume
As explained here, you may refer to the section:
正如解释在这里,您可以参考以下部分:
Core Audio APIs in Windows Vistafor more.
This call is not a Media Foundation call but a WASAPI (Windows Audio Session API) call: ISimpleAudioVolume::SetMasterVolume (The SetMasterVolume method sets the master volume level for the audio session.)
此调用不是 Media Foundation 调用,而是 WASAPI(Windows 音频会话 API)调用:ISimpleAudioVolume::SetMasterVolume(SetMasterVolume 方法设置音频会话的主音量级别。)
This may be difficult however to make the UI of the Media Center reflect the new sound level set by that call, as this thread illustratesit.
然而,这可能很难使 Media Center 的 UI 反映由该调用设置的新声音级别,如该线程所示。
For windows Xp, you can study this scriptand maybe this other script.
Audio Librarymight also be of interest.
对于Windows XP,你可以研究这个脚本,也许这个其他脚本。
音频库也可能感兴趣。
There is also this old Audio Projectwhich hasa master volume part:
还有这个旧的音频项目,它有一个主音量部分:
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;
}
回答by Alessandro Muzzi
Use this free library, it's simple and does the job. InputSimulator
使用这个免费的库,它很简单并且可以完成工作。 输入模拟器
It simulates a key press. You only have to add this reference and call wherever you want static methods like these:
它模拟按键操作。你只需要添加这个引用并在任何你想要静态方法的地方调用这些:
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_UP);
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_DOWN);
InputSimulator.SimulateKeyPress(VirtualKeyCode.VOLUME_MUTE);
Then, if you want to get the master vokume level do:
然后,如果你想获得主 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;
Doing this you'll have in level the current volume in 0-1 format (eg. 52% is 0.52) If you want to have it in 0-100 format simply do level*100
这样做,您将获得 0-1 格式的当前音量(例如,52% 为 0.52)如果您想将其设为 0-100 格式,只需执行 level*100