来源https://social.msdn.microsoft.com/Forums/zh-CN/ed054378-15c2-4607-975b-7b21ffaa39ce/setting-audio-level-in-windows-7?forum=windowspro-audiodevelopment
unit MMDevApi; {$MINENUMSIZE 4} {$WEAKPACKAGEUNIT} interface uses Windows, ActiveX, ComObj, propsys; const CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}'; IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}'; IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}'; IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}'; IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}'; IID_IAudioMeterInformation: TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}'; IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}'; // undocumented IID_IRemoteAudioSession: TGUID = '{33969B1D-D06F-4281-B837-7EAAFD21A9C0}'; IID_IAudioSessionQuerier: TGUID = '{94BE9D30-53AC-4802-829C-F13E5AD34776}'; IID_IAudioSessionQuery: TGUID = '{94BE9D30-53AC-4802-829C-F13E5AD34775}'; // IID_IAudioSessionEvents: TGUID = '{24918ACC-64B3-37C1-8CA9-74A66E9957A8}'; IID_IAudioSessionControl: TGUID = '{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}'; IID_ISimpleAudioVolume: TGUID = '{87CE5498-68D6-44E5-9215-6DA47EF883D8}'; IID_IAudioSessionManager: TGUID = '{BFA971F1-4D5E-40BB-935E-967039BFBEE4}'; IID_IAudioClient: TGUID = '{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}'; DEVICE_STATE_ACTIVE = $00000001; DEVICE_STATE_DISABLE = $00000002; DEVICE_STATE_NOTPRESENT = $00000004; DEVICE_STATE_UNPLUGGED = $00000008; DEVICE_STATEMASK_ALL = $0000000F; // QueryHardwareSupport ENDPOINT_HARDWARE_SUPPORT_VOLUME = $00000001; ENDPOINT_HARDWARE_SUPPORT_MUTE = $00000002; ENDPOINT_HARDWARE_SUPPORT_METER = $00000004; type EDataFlow = TOleEnum; const eRender = $00000000; eCapture = $00000001; eAll = $00000002; EDataFlow_enum_count = $00000003; type ERole = TOleEnum; const eConsole = $00000000; eMultimedia = $00000001; eCommunications = $00000002; ERole_enum_count = $00000003; // AudioSessionState AudioSessionStateInactive = 0; AudioSessionStateActive = 1; AudioSessionStateExpired = 2; // AudioSessionDisconnectReason DisconnectReasonDeviceRemoval = 0; DisconnectReasonServerShutdown = DisconnectReasonDeviceRemoval + 1; DisconnectReasonFormatChanged = DisconnectReasonServerShutdown + 1; DisconnectReasonSessionLogoff = DisconnectReasonFormatChanged + 1; DisconnectReasonSessionDisconnected = DisconnectReasonSessionLogoff + 1; DisconnectReasonExclusiveModeOverride = DisconnectReasonSessionDisconnected + 1; type PAUDIO_VOLUME_NOTIFICATION_DATA = ^AUDIO_VOLUME_NOTIFICATION_DATA; AUDIO_VOLUME_NOTIFICATION_DATA = packed record guidEventContext: TGUID; bMuted: BOOL; fMasterVolume: Single; nChannels: UINT; afChannelVolumes: array[1..1] of Single; end; type IAudioClient = interface(IUnknown) ['{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}'] end; IAudioEndpointVolumeCallback = interface(IUnknown) ['{657804FA-D6AD-4496-8A60-352752AF4F89}'] function OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HRESULT; stdcall; end; IAudioEndpointVolume = interface(IUnknown) ['{5CDF2C82-841E-4546-9722-0CF74078229A}'] function RegisterControlChangeNotify(pNotify: IAudioEndpointVolumeCallback): HRESULT; stdcall; function UnregisterControlChangeNotify(pNotify: IAudioEndpointVolumeCallback): HRESULT; stdcall; function GetChannelCount(var pnChannelCount: uint): HRESULT; stdcall; function SetMasterVolumeLevel(fLevelDB: Single; pguidEventContext: PGuid): HRESULT; stdcall; function SetMasterVolumeLevelScalar(fLevel: Single; pguidEventContext: PGuid): HRESULT; stdcall; function GetMasterVolumeLevel(var pfLevelDB: Single): HRESULT; stdcall ; function GetMasterVolumeLevelScalar(var pfLevel: Single): HRESULT; stdcall; function SetChannelVolumeLevel(nChannel: uint; fLevelDB: Single; pguidEventContext: PGuid): HRESULT; stdcall; function SetChannelVolumeLevelScalar(nChannel: uint; fLevel: Single; pguidEventContext: PGuid): HRESULT; stdcall ; function GetChannelVolumeLevel(nChannel: uint; fLevelDB: Single): HRESULT; stdcall; function GetChannelVolumeLevelScalar(nChannel: uint; fLevel: Single): HRESULT; stdcall; function SetMute(bMute: bool; pguidEventContext: PGuid): HRESULT; stdcall; function GetMute(var pbMute: bool): HRESULT; stdcall; function GetVolumeStepInfo(var pnStep: uint; var pnStepCount: uint): HRESULT; stdcall; function VolumeStepUp(pguidEventContext: PGuid): HRESULT; stdcall; function VolumeStepDown(pguidEventContext: PGuid): HRESULT; stdcall; function QueryHardwareSupport(var pdwHardwareSupportMask: uint): HRESULT; stdcall; function GetVolumeRange(var pflVolumeMindB: Single; var pflVolumeMaxdB: Single; var pflVolumeIncrementdB: Single): HRESULT; stdcall; end; IAudioMeterInformation = interface(IUnknown) ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}'] function GetPeakValue(out pfPeak: Single): HResult; stdcall; function GetMeteringChannelCount(out pnChannelCount: uint): HResult; stdcall; function GetChannelsPeakValues(u32ChannelCount: uint; afPeakValues: pSingle): HResult; stdcall; function QueryHardwareSupport(out pdwHardwareSupportMask: uint): HResult; stdcall; end; IMMDevice = interface(IUnknown) ['{D666063F-1587-4E43-81F1-B948E807363F}'] function Activate(const iid: TGUID; dwClsCtx: uint; pActivationParams: PPropVariant; out ppInterface: IUnknown): HRESULT; stdcall; function OpenPropertyStore(stgmAccess: integer; out ppProperties: IPropertyStore): HRESULT; stdcall; function GetId(ppstrId: PWChar): HRESULT; stdcall; function GetState(var pdwState: uint): HRESULT; stdcall; end; IMMDeviceCollection = interface(IUnknown) ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}'] function GetCount(var pcDevices: uint): HRESULT; stdcall; function Item(nDevice: uint; out ppDevice: IMMDevice): HRESULT; stdcall; end; IMMNotificationClient = interface(IUnknown) ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}'] end; IMMDeviceEnumerator = interface(IUnknown) ['{A95664D2-9614-4F35-A746-DE8DB63617E6}'] function EnumAudioEndpoints(dataFlow: EDataFlow; dwStateMask: DWORD; out ppDevices: IMMDeviceCollection): HRESULT; stdcall; function GetDefaultAudioEndpoint(dataFlow: EDataFlow; role: ERole; out ppEndpoint: IMMDevice): HRESULT; stdcall; function GetDevice(pwstrId: PWChar; out ppDevice: IMMDevice): HRESULT; stdcall; function RegisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall; function UnregisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall; end; { undocumented } IRemoteAudioSession = interface(IUnknown) ['{33969B1D-D06F-4281-B837-7EAAFD21A9C0}'] function func_a: HResult; stdcall; function func_b: HResult; stdcall; function func_c: HResult; stdcall; function func_d: HResult; stdcall; function func_e: HResult; stdcall; function func_f: HResult; stdcall; function func_g: HResult; stdcall; function func_h: HResult; stdcall; function func_i: HResult; stdcall; function func_j: HResult; stdcall; function func_k: HResult; stdcall; function GetProcessID(out pid: uint): HResult; stdcall; end; { undocumented } IAudioSessionQuerier = interface(IUnknown) ['{94BE9D30-53AC-4802-829C-F13E5AD34776}'] function GetNumSessions(out NumSessions: uint): HResult; stdcall; function QuerySession(Num: uint; out Session: IUnknown): HResult; stdcall; end; { undocumented } IAudioSessionQuery = interface(IUnknown) ['{94BE9D30-53AC-4802-829C-F13E5AD34775}'] function GetQueryInterface(out AudioQuerier: IAudioSessionQuerier): HResult; stdcall; end; IAudioSessionEvents = interface(IUnknown) ['{24918ACC-64B3-37C1-8CA9-74A66E9957A8}'] function OnDisplayNameChanged(NewDisplayName: LPCWSTR; EventContext: pGuid): HResult; stdcall; function OnIconPathChanged(NewIconPath: LPCWSTR; EventContext: pGuid): HResult; stdcall; function OnSimpleVolumeChanged(NewVolume: Single; NewMute: LongBool; EventContext: pGuid): HResult; stdcall; function OnChannelVolumeChanged(ChannelCount: uint; NewChannelArray: PSingle; ChangedChannel: uint; EventContext: pGuid): HResult; stdcall; function OnGroupingParamChanged(NewGroupingParam, EventContext: pGuid): HResult; stdcall; function OnStateChanged(NewState: uint): HResult; stdcall; // AudioSessionState function OnSessionDisconnected(DisconnectReason: uint): HResult; stdcall; // AudioSessionDisconnectReason end; IAudioSessionControl = interface(IUnknown) ['{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}'] function GetState(out pRetVal: uint): HResult; stdcall; function GetDisplayName(out pRetVal: LPWSTR): HResult; stdcall; // pRetVal must be freed by CoTaskMemFree function SetDisplayName(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall; function GetIconPath(out pRetVal: LPWSTR): HResult; stdcall; // pRetVal must be freed by CoTaskMemFree function SetIconPath(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall; function GetGroupingParam(pRetVal: pGuid): HResult; stdcall; function SetGroupingParam(OverrideValue, EventContext: pGuid): HResult; stdcall; function RegisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents): HResult; stdcall; function UnregisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents): HResult; stdcall; end; ISimpleAudioVolume = interface(IUnknown) ['{87CE5498-68D6-44E5-9215-6DA47EF883D8}'] function SetMasterVolume(fLevel: Single; EventContext: pGuid): HResult; stdcall; function GetMasterVolume(out fLevel: Single): HResult; stdcall; function SetMute(bMute: LongBool; EventContext: pGuid): HResult; stdcall; function GetMute(out bMute: LongBool): HResult; stdcall; end; IAudioSessionManager = interface(IUnknown) ['{BFA971F1-4D5E-40BB-935E-967039BFBEE4}'] function GetAudioSessionControl(AudioSessionGuid: pGUID; StreamFlag: uint; out SessionControl: IAudioSessionControl): HResult; stdcall; function GetSimpleAudioVolume(AudioSessionGuid: pGuid; StreamFlag: uint; out AudioVolume: ISimpleAudioVolume): HResult; stdcall; end; // get ISimpleAudioVolume from ProcessID function GetSimpleAudioVolumeFromPid(const AudioDevice: IMMDevice; pid: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; // get ISimpleAudioVolume from Process Handle function GetSimpleAudioVolumeFromHandle(const AudioDevice: IMMDevice; Hnd: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; // function GetSimpleAudioVolumeFromModuleName(const AudioDevice: IMMDevice; ModuleName: pWideChar; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; implementation uses tlhelp32; function GetProcessIdFromModuleName(ModuleName: pWideChar): LongWord; var ToolSnap: LongWord; ProcessEntry: ProcessEntry32W; bCont: LongBool; ModuleName16: WideString; begin Result := 0; ModuleName16 := ModuleName; ToolSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ProcessEntry.dwSize := sizeof(ProcessEntry); bCont := Process32FirstW(ToolSnap, ProcessEntry); while bCont do begin if ProcessEntry.szExeFile = ModuleName16 then Result := ProcessEntry.th32ProcessID; ProcessEntry.dwSize := sizeof(ProcessEntry); bCont := (Result = 0) and Process32NextW(ToolSnap, ProcessEntry); end; CloseHandle(ToolSnap); end; function GetSimpleAudioVolumeFromModuleName(const AudioDevice: IMMDevice; ModuleName: pWideChar; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var pid: LongWord; begin pid := GetProcessIdFromModuleName(ModuleName); Result := GetSimpleAudioVolumeFromPid(AudioDevice, pid, SimpleAudio, currguid); end; function GetSimpleAudioVolumeFromHandle(const AudioDevice: IMMDevice; Hnd: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var pid: uint; begin GetWindowThreadProcessId(Hnd, pid); Result := GetSimpleAudioVolumeFromPid(AudioDevice, pid, SimpleAudio, currguid); end; function GetSimpleAudioVolumeFromPid(const AudioDevice: IMMDevice; pid: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var SessionManager: IAudioSessionManager; SessionQuery: IAudioSessionQuery; SessionQuerier: IAudioSessionQuerier; RemoteSession: IRemoteAudioSession; SessionControl: IAudioSessionControl; dummy: IUnknown; MaxSession, Sessionpid: uint; hr, i: Integer; begin Result := False; SessionManager := nil; SessionQuery := nil; SessionQuerier := nil; SessionControl := nil; // get AudioSessionManager hr := AudioDevice.Activate(IID_IAudioSessionManager, CLSCTX_ALL, nil, IUnknown(SessionManager)); if Succeeded(hr) then begin // get SessionQuery hr := SessionManager.QueryInterface(IID_IAudioSessionQuery, SessionQuery); if Succeeded(hr) then begin // get SessionQuerier hr := SessionQuery.GetQueryInterface(SessionQuerier); if Succeeded(hr) then begin // check sessions hr := SessionQuerier.GetNumSessions(MaxSession); if Succeeded(hr) then if MaxSession > 0 then for i := 0 to MaxSession - 1 do begin dummy := nil; hr := SessionQuerier.QuerySession(i, dummy); RemoteSession := nil; if Succeeded(hr) then begin // get RemoteSession hr := dummy.QueryInterface(IID_IRemoteAudioSession, RemoteSession); if Succeeded(hr) then begin // compare ProcessID if Succeeded(RemoteSession.GetProcessID(Sessionpid)) then if Sessionpid <> 0 then if Sessionpid = pid then begin Result := Succeeded(RemoteSession.QueryInterface(IID_ISimpleAudioVolume, SimpleAudio)); if Succeeded(dummy.QueryInterface(IID_IAudioSessionControl, SessionControl)) then SessionControl.GetGroupingParam(@currguid); SessionControl := nil; end; if Result then Break; end; end; end; RemoteSession := nil; SessionQuerier := nil; end; SessionQuery := nil; end; SessionManager := nil; end; end; end.
In a new project I did this:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActiveX, MMDevApi, StdCtrls, Buttons, ComCtrls, Spin, Math; type TForm1 = class(TForm) TrackBar1: TTrackBar; CheckBox1: TCheckBox; procedure FormCreate(Sender: TObject); procedure TrackBar1Change(Sender: TObject); procedure CheckBox1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; endpointVolume: IAudioEndpointVolume = nil; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var deviceEnumerator: IMMDeviceEnumerator; defaultDevice: IMMDevice; b: LongBool; VolumeLevel: Single; begin CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator); deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice); defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, IUnknown(endpointVolume)); if endpointVolume = nil then Exit; endpointVolume.GetMute(b); checkbox1.Checked := b; endpointVolume.GetMasterVolumeLevelScalar(VolumeLevel); TrackBar1.Position := Round(100 - 100 * VolumeLevel); end; procedure TForm1.TrackBar1Change(Sender: TObject); var VolumeLevel: Single; begin //Master Volume if endpointVolume = nil then Exit; VolumeLevel := 0.01 * (100 - TrackBar1.Position); endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil); end; procedure TForm1.CheckBox1Click(Sender: TObject); var b: LongBool; begin //Mute on/off if endpointVolume = nil then Exit; b := CheckBox1.Checked; endpointVolume.SetMute(b, nil); end; end.