不进则退

Roger's blog @cnblogs

导航

在.NET程序中控制系统音量

在windows下控制系统音量,需要通过使用win32的WDM audio components(winmm.dll)来实现,为了方便起见,将其封装到了一个AudioMixerHelper类中,可以直接通过GetVolume()和SetVolume方法来改变音量。

using System;

using System.Runtime.InteropServices;

 

namespace Microsoft

{

 

     
public 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 ,00);

              
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 ,00);

              
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);

         }


     }


}


 

本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利

posted on 2005-02-22 16:43  Roger Wo  阅读(3510)  评论(7编辑  收藏  举报