一直想控制系统音量,但是似乎C#都有着很多的问题,索性去看API。
最后找到了一个外国友人的东西,外国友人写的类就是好看,感觉比自己写的要规范好多啊!
自己使用了此类后发现了一个问题,在XP系统下正常,但是Win7以上都不能正常使用。
然后又查了一下官方的解释,原来微软win7后就改动了底层的音量控制的东西。
现在贴出来,希望大家对大家有帮助,在后面将讲解在Win7及其以上怎么操作系统音量的问题!
class AudioMixerHelper { public const int MMSYSERR_NOERROR = 0; public const int MAXPNAMELEN = 32; public const int MIXER_LONG_NAME_CHARS = 64; public const int MIXER_SHORT_NAME_CHARS = 16; public const int MIXER_GETLINEINFOF_COMPONENTTYPE = 0x3; public const int MIXER_GETCONTROLDETAILSF_VALUE = 0x0; public const int MIXER_GETLINECONTROLSF_ONEBYTYPE = 0x2; public const int MIXER_SETCONTROLDETAILSF_VALUE = 0x0; public const int MIXERLINE_COMPONENTTYPE_DST_FIRST = 0x0; public const int MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x1000; public const int MIXERLINE_COMPONENTTYPE_DST_SPEAKERS =(MIXERLINE_COMPONENTTYPE_DST_FIRST + 4); public const int MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE =(MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3); public const int MIXERLINE_COMPONENTTYPE_SRC_LINE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2); public const int MIXERCONTROL_CT_CLASS_FADER = 0x50000000; public const int MIXERCONTROL_CT_UNITS_UNSIGNED = 0x30000; public const int MIXERCONTROL_CONTROLTYPE_FADER = (MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED); public const int MIXERCONTROL_CONTROLTYPE_VOLUME = (MIXERCONTROL_CONTROLTYPE_FADER + 1); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerClose (int hmx); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetControlDetailsA (int hmxobj,ref MIXERCONTROLDETAILS pmxcd , int fdwDetails); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetDevCapsA(int uMxId, MIXERCAPS pmxcaps, int cbmxcaps); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetID (int hmxobj, int pumxID, int fdwId); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetLineControlsA (int hmxobj,ref MIXERLINECONTROLS pmxlc, int fdwControls); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetLineInfoA (int hmxobj,ref MIXERLINE pmxl , int fdwInfo); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerGetNumDevs(); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerMessage(int hmx , int uMsg , int dwParam1 , int dwParam2); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerOpen (out int phmx , int uMxId ,int dwCallback , int dwInstance , int fdwOpen); [DllImport("winmm.dll", CharSet=CharSet.Ansi)] private static extern int mixerSetControlDetails(int hmxobj ,ref MIXERCONTROLDETAILS pmxcd , int fdwDetails); public struct MIXERCAPS { public int wMid; public int wPid; public int vDriverVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAXPNAMELEN)] public string szPname; public int fdwSupport; public int cDestinations; } public struct MIXERCONTROL { public int cbStruct; public int dwControlID; public int dwControlType; public int fdwControl; public int cMultipleItems; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MIXER_SHORT_NAME_CHARS)] public string szShortName ; [MarshalAs( UnmanagedType.ByValTStr,SizeConst=MIXER_LONG_NAME_CHARS)] public string szName; public int lMinimum; public int lMaximum; [MarshalAs(UnmanagedType.U4, SizeConst=10)] public int reserved; } public struct MIXERCONTROLDETAILS { public int cbStruct; public int dwControlID; public int cChannels; public int item; public int cbDetails; public IntPtr paDetails; } public struct MIXERCONTROLDETAILS_UNSIGNED { public int dwValue; } public struct MIXERLINE { public int cbStruct; public int dwDestination; public int dwSource; public int dwLineID; public int fdwLine; public int dwUser; public int dwComponentType; public int cChannels; public int cConnections; public int cControls; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MIXER_SHORT_NAME_CHARS)] public string szShortName; [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MIXER_LONG_NAME_CHARS )] public string szName; public int dwType; public int dwDeviceID; public int wMid; public int wPid; public int vDriverVersion ; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAXPNAMELEN)] public string szPname ; } public struct MIXERLINECONTROLS { public int cbStruct; public int dwLineID; public int dwControl; public int cControls; public int cbmxctrl; public IntPtr pamxctrl; } private static bool GetVolumeControl(int hmixer, int componentType,int ctrlType, out MIXERCONTROL mxc, out int vCurrentVol) { // This function attempts to obtain a mixer control. // Returns True if successful. MIXERLINECONTROLS mxlc = new MIXERLINECONTROLS(); MIXERLINE mxl = new MIXERLINE(); MIXERCONTROLDETAILS pmxcd = new MIXERCONTROLDETAILS(); MIXERCONTROLDETAILS_UNSIGNED du = new MIXERCONTROLDETAILS_UNSIGNED(); mxc = new MIXERCONTROL(); int rc; bool retValue; vCurrentVol = -1; mxl.cbStruct = Marshal.SizeOf(mxl); mxl.dwComponentType = componentType; rc = mixerGetLineInfoA(hmixer,ref mxl,MIXER_GETLINEINFOF_COMPONENTTYPE ); if(MMSYSERR_NOERROR == rc) { int sizeofMIXERCONTROL = 152; int ctrl = Marshal.SizeOf(typeof(MIXERCONTROL)); mxlc.pamxctrl = Marshal.AllocCoTaskMem(sizeofMIXERCONTROL); mxlc.cbStruct = Marshal.SizeOf(mxlc); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControl = ctrlType; mxlc.cControls = 1; mxlc.cbmxctrl = sizeofMIXERCONTROL; // Allocate a buffer for the control mxc.cbStruct = sizeofMIXERCONTROL; // Get the control rc = mixerGetLineControlsA(hmixer,ref mxlc,MIXER_GETLINECONTROLSF_ONEBYTYPE); if(MMSYSERR_NOERROR == rc) { retValue = true; // Copy the control into the destination structure mxc = (MIXERCONTROL)Marshal.PtrToStructure(mxlc.pamxctrl,typeof(MIXERCONTROL)); } else { retValue = false; } int sizeofMIXERCONTROLDETAILS = Marshal.SizeOf(typeof(MIXERCONTROLDETAILS)); int sizeofMIXERCONTROLDETAILS_UNSIGNED = Marshal.SizeOf(typeof(MIXERCONTROLDETAILS_UNSIGNED)); pmxcd.cbStruct = sizeofMIXERCONTROLDETAILS; pmxcd.dwControlID = mxc.dwControlID; pmxcd.paDetails = Marshal.AllocCoTaskMem(sizeofMIXERCONTROLDETAILS_UNSIGNED) ; pmxcd.cChannels = 1; pmxcd.item = 0; pmxcd.cbDetails = sizeofMIXERCONTROLDETAILS_UNSIGNED; rc = mixerGetControlDetailsA(hmixer,ref pmxcd,MIXER_GETCONTROLDETAILSF_VALUE); du = (MIXERCONTROLDETAILS_UNSIGNED)Marshal.PtrToStructure(pmxcd.paDetails, typeof(MIXERCONTROLDETAILS_UNSIGNED)); vCurrentVol = du.dwValue; return retValue; } retValue = false; return retValue; } private static bool SetVolumeControl(int hmixer, MIXERCONTROL mxc,int volume) { // This function sets the value for a volume control. // Returns True if successful bool retValue; int rc; MIXERCONTROLDETAILS mxcd = new MIXERCONTROLDETAILS(); MIXERCONTROLDETAILS_UNSIGNED vol = new MIXERCONTROLDETAILS_UNSIGNED(); mxcd.item = 0; mxcd.dwControlID = mxc.dwControlID; mxcd.cbStruct = Marshal.SizeOf(mxcd); mxcd.cbDetails = Marshal.SizeOf(vol); // Allocate a buffer for the control value buffer mxcd.cChannels = 1; vol.dwValue = volume; // Copy the data into the control value buffer mxcd.paDetails = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(MIXERCONTROLDETAILS_UNSIGNED))); Marshal.StructureToPtr(vol, mxcd.paDetails,false); // Set the control value rc = mixerSetControlDetails(hmixer,ref mxcd,MIXER_SETCONTROLDETAILSF_VALUE); if(MMSYSERR_NOERROR == rc) { retValue = true; } else { retValue = false; } return retValue; } public static int GetVolume() { int mixer; MIXERCONTROL volCtrl = new MIXERCONTROL(); int currentVol; mixerOpen(out mixer,0 ,0 ,0, 0); int type = MIXERCONTROL_CONTROLTYPE_VOLUME; GetVolumeControl(mixer,MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,type,out volCtrl, out currentVol); mixerClose(mixer); return currentVol; } public static void SetVolume(int vVolume) { int mixer; MIXERCONTROL volCtrl = new MIXERCONTROL(); int currentVol; mixerOpen(out mixer,0 ,0 ,0, 0); int type = MIXERCONTROL_CONTROLTYPE_VOLUME; GetVolumeControl(mixer,MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,type,out volCtrl, out currentVol); if(vVolume > volCtrl.lMaximum) vVolume = volCtrl.lMaximum; if(vVolume < volCtrl.lMinimum) vVolume = volCtrl.lMinimum; SetVolumeControl(mixer, volCtrl, vVolume); GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,type,out volCtrl, out currentVol); if(vVolume != currentVol) { throw new Exception("Cannot Set Volume"); } mixerClose(mixer); } }