how to adjust master volume in vista/xp

让人想犯罪 __ 提交于 2019-12-01 05:58:59
Sebastian Oliva

Here's the implementation of a general purpose api for audio: MMDevApi

http://social.msdn.microsoft.com/Forums/en/windowspro-audiodevelopment/thread/5ce74d5d-2b1e-4ca9-a8c9-2e27eb9ec058

and an example with a button

unit Unit33;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, MMDevApi, ActiveX, StdCtrls;

type
  TForm33 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form33: TForm33;
  endpointVolume: IAudioEndpointVolume = nil;

implementation

{$R *.dfm}


procedure TForm33.Button1Click(Sender: TObject);
var
  VolumeLevel: Single;
begin
  if endpointVolume = nil then Exit;
  VolumeLevel := 0.50;
  endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);
  Caption := Format('%1.8f', [VolumeLevel])
end;

procedure TForm33.FormCreate(Sender: TObject);
var
  deviceEnumerator: IMMDeviceEnumerator;
  defaultDevice: IMMDevice;
begin
  CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);
  deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);
  defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
end;

end.

Windows XP:

function SetMasterVolume(VolToSet: word; out VolSet: word): MMResult;
var
  MixerHandle: HMixer;
  Volume: TMixerControlDetails_Unsigned;
  MixerLine: TMixerLine;
  MixerLineControls: TMixerLineControls;
  VolumeCtrl: TMixerControl;
  MixerControlDetails: TMixerControlDetails;
begin
  // Get mixer handle
  Result := mixerOpen(@MixerHandle, 0, 0, 0, 0);
  if Result <> MMSYSERR_NOERROR then Exit;
  try
    // Get master volume line
    FillChar(MixerLine, SizeOf(TMixerLine), 0);
    MixerLine.cbStruct := SizeOf(TMixerLine);
    MixerLine.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
    Result := mixerGetLineInfo(MixerHandle, @MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);

    if Result <> MMSYSERR_NOERROR then Exit;
    // Get the volume control of the master volume line
    FillChar(VolumeCtrl, SizeOf(TMixerControl), 0);
    MixerLineControls.cbStruct := SizeOf(TMixerLineControls);
    MixerLineControls.dwLineID := MixerLine.dwLineID;
    MixerLineControls.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
    MixerLineControls.cControls := 1;
    MixerLineControls.cbmxctrl := SizeOf(TMixerControl);
    MixerLineControls.pamxctrl := @VolumeCtrl;
    Result := mixerGetLineControls(MixerHandle,@MixerLineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE);

    if Result <> MMSYSERR_NOERROR then Exit;
    // Set details (volume) for the volume control of the master volume line
    FillChar(MixerControlDetails, SizeOf(TMixerControlDetails), 0);
    MixerControlDetails.cbStruct := SizeOf(TMixerControlDetails);
    MixerControlDetails.dwControlID := VolumeCtrl.dwControlID;
    MixerControlDetails.cChannels := 1;
    MixerControlDetails.cMultipleItems := 0;
    MixerControlDetails.cbDetails := SizeOf(TMixerControlDetails_Unsigned);
    MixerControlDetails.paDetails := @Volume;
    Volume.dwValue := VolToSet;
    Result := mixerSetControlDetails(MixerHandle, @MixerControlDetails,MIXER_SETCONTROLDETAILSF_VALUE);
  finally
    mixerClose(MixerHandle);
  end;
end;

And the call:

var y:word;
begin
  SetMasterVolume(2000,y);
end;

Final code is(for Delphi 7):

unit DevUnit;


interface

uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;


const
  // TypeLibrary Major and minor versions
  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}';
  DEVICE_STATE_ACTIVE                   = $00000001;
  DEVICE_STATE_UNPLUGGED                = $00000002;
  DEVICE_STATE_NOTPRESENT               = $00000004;
  DEVICE_STATEMASK_ALL                  = $00000007;

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;

type

  IAudioEndpointVolumeCallback = interface(IUnknown)
  ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
  end;

  IMMAudioEndpointVolume = interface(IUnknown)
  ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
    Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    Function GetChannelCount(out PInteger): Integer; stdcall;
    Function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
    Function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
    Function GetMasterVolumeLevel(out fLevelDB: single):Integer; stdcall;
    Function GetMasterVolumeLevelScaler(out fLevel: single):Integer; stdcall;
    Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
    Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
    Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: single) : Integer; stdcall;
    Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: single) : Integer; stdcall;
    Function SetMute(bMute: Boolean ; pguidEventContext: PGUID) :Integer; stdcall;
    Function GetMute(out bMute: Boolean ) :Integer; stdcall;
    Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;
    Function VolumeStepUp(pguidEventContext: PGUID) :Integer; stdcall;
    Function VolumeStepDown(pguidEventContext: PGUID) :Integer; stdcall;
    Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
    Function GetVolumeRange(out pflVolumeMindB: single; out pflVolumeMaxdB: single; out pflVolumeIncrementdB: single): Integer; stdcall;
  end;

  IPropertyStore = interface(IUnknown)
  end;

type
  IMMDevice = interface(IUnknown)
  ['{D666063F-1587-4E43-81F1-B948E807363F}']
    Function Activate(  refId :PGUID;
                        dwClsCtx: DWORD;
                        pActivationParams: PInteger ;
                        out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;
    Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;
    Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;
    Function GetState(out State :Integer): Hresult; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
  ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
  end;
  IMMNotificationClient = interface (IUnknown)
  ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
  end;
  IMMDeviceEnumerator = interface(IUnknown)
  ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;
    Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;
    Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;
    Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall;
  end;
  implementation
end.

The MMDevApi has a number of incorrect declarations. The double parameters should be single. The Boolean parameters work better as integer. And many if not all of the TGUID parameters should be PGUID. After correcting the declarations I was able to set the mute and the volume level.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!