您的位置:首页 > 编程语言 > C#

[C#] 控制系统音量-第一章

2014-03-06 17:12 344 查看
一直想控制系统音量,但是似乎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);
        }
    }


转载请注明出处!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: