【问题标题】:how to adjust master volume in vista/xpvista/xp中如何调整主音量
【发布时间】:2011-03-27 02:36:03
【问题描述】:

我想像 vista 和 xp 中的 Get/SetMasterVolume 那样以编程方式调整音量?使用 mmsystem 单元?

【问题讨论】:

    标签: delphi windows-vista windows-xp media volume


    【解决方案1】:

    这是一个通用的音频 api 的实现:MMDevApi

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

    还有一个带按钮的例子

    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.
    

    【讨论】:

    【解决方案2】:

    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;
    

    然后打电话:

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

    【讨论】:

      【解决方案3】:

      最终代码是(对于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.
      

      【讨论】:

        【解决方案4】:

        MMDevApi 有许多不正确的声明。双参数应该是单参数。布尔参数作为整数更好地工作。许多(如果不是全部)TGUID 参数应该是 PGUID。更正声明后,我可以设置静音和音量级别。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-29
          • 2010-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多