private static WinXpDllInterface.MIXER InnerGetMixer(int i, uint type, uint ctrlType, out int currVolume) { currVolume = -1; WinXpDllInterface.LINECONTROLS mlc = new WinXpDllInterface.LINECONTROLS(); WinXpDllInterface.MIXERLINE mxl = new WinXpDllInterface.MIXERLINE(); WinXpDllInterface.MIXERDETAILS xdl = new WinXpDllInterface.MIXERDETAILS(); WinXpDllInterface.UMIXERDETAILS uxdl = new WinXpDllInterface.UMIXERDETAILS(); WinXpDllInterface.MIXER mixerControl = new WinXpDllInterface.MIXER(); mxl.cbStruct = (uint)Marshal.SizeOf(mxl); mxl.dwComponentType = (uint)type; int details = WinXpDllInterface.mixerGetLineInfoA(i, ref mxl, WinXpDllInterface.MIXER_GETLINEINFOF_COMPONENTTYPE); if (WinXpDllInterface.MMSYSERR_NOERROR == details) { int mcSize = 152; int control = Marshal.SizeOf(typeof(WinXpDllInterface.MIXER)); mlc.pamxctrl = Marshal.AllocCoTaskMem(mcSize); mlc.cbStruct = (uint)Marshal.SizeOf(mlc); mlc.dwLineID = mxl.dwLineID; mlc.dwControl = (uint)ctrlType; mlc.cControls = 1; mlc.cbmxctrl = (uint)mcSize; mixerControl.cbStruct = mcSize; details = WinXpDllInterface.mixerGetLineControlsA(i, ref mlc, WinXpDllInterface.MIXER_GETLINECONTROLSF_ONEBYTYPE); bool result = WinXpDllInterface.MMSYSERR_NOERROR == details; if (result) { mixerControl = (WinXpDllInterface.MIXER)Marshal.PtrToStructure(mlc.pamxctrl, typeof(WinXpDllInterface.MIXER)); int mcDetailsSize = Marshal.SizeOf(typeof(WinXpDllInterface.MIXERDETAILS)); int mcDetailsUnsigned = Marshal.SizeOf(typeof(WinXpDllInterface.UMIXERDETAILS)); xdl.cbStruct = mcDetailsSize; xdl.dwControlID = mixerControl.dwControlID; xdl.paDetails = Marshal.AllocCoTaskMem(mcDetailsUnsigned); xdl.cChannels = 1; xdl.item = 0; xdl.cbDetails = mcDetailsUnsigned; details = WinXpDllInterface.mixerGetControlDetailsA(i, ref xdl, WinXpDllInterface.MIXER_GETCONTROLDETAILSF_VALUE); uxdl = (WinXpDllInterface.UMIXERDETAILS)Marshal.PtrToStructure(xdl.paDetails, typeof(WinXpDllInterface.UMIXERDETAILS)); currVolume = uxdl.dwValue; return(mixerControl); } } return(mixerControl); }
private static bool InnerSetMixer(int i, WinXpDllInterface.MIXER mixer, int volume) { WinXpDllInterface.MIXERDETAILS xdl = new WinXpDllInterface.MIXERDETAILS(); WinXpDllInterface.UMIXERDETAILS uxdl = new WinXpDllInterface.UMIXERDETAILS(); xdl.item = 0; xdl.dwControlID = mixer.dwControlID; xdl.cbStruct = Marshal.SizeOf(xdl); xdl.cbDetails = Marshal.SizeOf(uxdl); xdl.cChannels = 1; uxdl.dwValue = volume; xdl.paDetails = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(WinXpDllInterface.UMIXERDETAILS))); Marshal.StructureToPtr(uxdl, xdl.paDetails, false); int details = WinXpDllInterface.mixerSetControlDetails(i, ref xdl, WinXpDllInterface.MIXER_SETCONTROLDETAILSF_VALUE); return(WinXpDllInterface.MMSYSERR_NOERROR == details); }
private static void SetVolume(int volume) { InvokeTryCatch("WinXpVolumeOperate.SetVolume", () => { int currVolume; int mixerControl; WinXpDllInterface.mixerOpen(out mixerControl, 0, 0, 0, 0); uint controlType = WinXpDllInterface.MIXERCONTROL_CONTROLTYPE_VOLUME; WinXpDllInterface.MIXER mixer = InnerGetMixer(mixerControl, WinXpDllInterface.MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, controlType, out currVolume); bool setSucceed = false; for (int i = 0; i < 3; i++) { if (volume > mixer.lMaximum) { volume = mixer.lMaximum; } if (volume < mixer.lMinimum) { volume = mixer.lMinimum; } InnerSetMixer(mixerControl, mixer, volume); mixer = InnerGetMixer(mixerControl, WinXpDllInterface.MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, controlType, out currVolume); if (volume == currVolume) { setSucceed = true; break; } //如果设置失败, 则最多重试3次 } WinXpDllInterface.mixerClose(mixerControl); if (!setSucceed) { throw new Exception("多次尝试设置 Xp操作系统音量 失败 (该异常可能是偶发异常, 可以忽略)!"); } }); }