来自How to check if the system master volume is mute or unmute?的代码示例,但有一些更改。
function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): HRESULT; stdcall;
function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): HRESULT; stdcall;
fLevelDB从double到single。双结果总是0。 而对于
function SetMute(bMute: Boolean; pguidEventContext: PGUID): HRESULT; stdcall;
function GetMute(out bMute: Boolean): HRESULT; stdcall;
从布尔到整数(0-false 1-true)
无法使SetChannelVolumeLevelScalar / SetChannelVolumeLevel工作,这个函数首先让我陷入困境。
演示代码
unit MasterVolumeControl;
interface
uses
SysUtils,
Windows,
ActiveX,
ComObj;
const
CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
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;
IAudioEndpointVolume = interface(IUnknown)
['{5CDF2C82-841E-4546-9722-0CF74078229A}']
function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): HRESULT; stdcall;
function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): HRESULT; stdcall;
function GetChannelCount(out PInteger): HRESULT; stdcall;
function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): HRESULT; stdcall;
function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): HRESULT; stdcall;
function GetMasterVolumeLevel(out fLevelDB: single): HRESULT; stdcall;
function GetMasterVolumeLevelScaler(out fLevelDB: single): HRESULT; stdcall;
function SetChannelVolumeLevel(nChannel: uint; fLevelDB: double; pguidEventContext: PGUID): HRESULT; stdcall;
function SetChannelVolumeLevelScalar(nChannel: uint; fLevelDB: double; pguidEventContext: PGUID): HRESULT; stdcall;
function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): HRESULT; stdcall;
function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: single): HRESULT; stdcall;
function SetMute(bMute: Integer; pguidEventContext: PGUID): HRESULT; stdcall;
function GetMute(out bMute: Integer): HRESULT; stdcall;
function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): HRESULT; stdcall;
function VolumeStepUp(pguidEventContext: PGUID): HRESULT; stdcall;
function VolumeStepDown(pguidEventContext: PGUID): HRESULT; stdcall;
function QueryHardwareSupport(out pdwHardwareSupportMask): HRESULT; stdcall;
function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): HRESULT; stdcall;
end;
IAudioMeterInformation = interface(IUnknown)
['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
end;
IPropertyStore = interface(IUnknown)
end;
IMMDevice = interface(IUnknown)
['{D666063F-1587-4E43-81F1-B948E807363F}']
function Activate(const refId: TGUID; dwClsCtx: DWORD; pActivationParams: PInteger; out pEndpointVolume: IAudioEndpointVolume): 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: TOleEnum; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): HRESULT; stdcall;
function GetDefaultAudioEndpoint(EDF: EDataFlow; ER: SYSUINT; out Dev: IMMDevice): HRESULT; stdcall;
function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HRESULT; stdcall;
function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): HRESULT; stdcall;
end;
var
pEndpointVolume : IAudioEndpointVolume;
LDeviceEnumerator: IMMDeviceEnumerator;
Dev : IMMDevice;
procedure SetMasterVolume(fLevelDB: single);
function GetMasterVolume(): single;
function GetNumberOfChannels: Integer;
function GetChannelVolume(Channel: DWORD): single;
procedure SetVolumeChannel(fLevelDB: single; Channel: uint);
procedure SetMute(mute: Boolean);
function GetMute(): Boolean;
implementation
procedure SetMasterVolume(fLevelDB: single);
begin
if not Succeeded(pEndpointVolume.SetMasterVolumeLevelScalar(fLevelDB, @GUID_NULL)) then
RaiseLastOSError;
end;
function GetMasterVolume(): single;
begin
if not Succeeded(pEndpointVolume.GetMasterVolumeLevelScaler(result)) then
RaiseLastOSError;
end;
function GetChannelVolume(Channel: DWORD): single;
begin
if not Succeeded(pEndpointVolume.GetChannelVolumeLevelScalar(Channel, result)) then
RaiseLastOSError;
end;
procedure SetVolumeChannel(fLevelDB: single; Channel: uint);
begin
if not Succeeded(pEndpointVolume.SetChannelVolumeLevelScalar(Channel, fLevelDB, @GUID_NULL)) then
RaiseLastOSError;
end;
procedure SetMute(mute: Boolean);
var
iMute: Integer;
begin
iMute := 0;
if mute then
iMute := 1;
if not Succeeded(pEndpointVolume.SetMute(iMute, nil)) then
RaiseLastOSError;
end;
function GetMute(): Boolean;
var
mute: Integer;
begin
if not Succeeded(pEndpointVolume.GetMute(mute)) then
RaiseLastOSError;
result := true;
if mute = 0 then
result := false;
end;
function GetNumberOfChannels: Integer;
begin
if not Succeeded(pEndpointVolume.GetChannelCount(result)) then
RaiseLastOSError;
end;
initialization
if not Succeeded(CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, LDeviceEnumerator)) then
RaiseLastOSError;
if not Succeeded(LDeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, Dev)) then
RaiseLastOSError;
if not Succeeded(Dev.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, pEndpointVolume)) then
RaiseLastOSError;
end.
并形成:
unit uVolumeControlExample;
interface
uses
MasterVolumeControl,
Vcl.ComCtrls,
System.Classes,
Vcl.Controls,
Vcl.StdCtrls,
Vcl.Forms,
sysutils;
type
TForm8 = class(TForm)
chkMute: TCheckBox;
masterVolume: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure chkMuteClick(Sender: TObject);
procedure FormResize(Sender: TObject);
private
noOfChannels: integer;
channels : TStringList;
procedure TrackBarChange(Sender: TObject);
procedure RefreshChannels;
public
{ Public declarations }
end;
var
Form8: TForm8;
implementation
{$R *.dfm}
procedure TForm8.chkMuteClick(Sender: TObject);
begin
SetMute(chkMute.Checked);
end;
procedure TForm8.FormCreate(Sender: TObject);
var
I: integer;
begin
channels := TStringList.Create;
noOfChannels := GetNumberOfChannels;
for I := 0 to noOfChannels - 1 do begin
channels.AddObject('Channel_' + IntToStr(I), TTrackBar.Create(self));
with TTrackBar(channels.Objects[I]) do begin
Visible := false;
Parent := self;
Tag := I;
Left := 8;
Top := 8 + I * 45;
Width := 345;
Height := 45;
OnChange := TrackBarChange;
Max := 100;
Name := 'Channel_' + IntToStr(I);
Visible := true;
end;
end;
with masterVolume do begin
Visible := false;
Tag := noOfChannels;
Left := 8;
Top := 8 + noOfChannels * 45;
Width := 345;
Height := 45;
OnChange := TrackBarChange;
Max := 100;
Visible := true;
end;
RefreshChannels;
end;
procedure TForm8.FormDestroy(Sender: TObject);
begin
channels.Free;
end;
procedure TForm8.FormResize(Sender: TObject);
begin
RefreshChannels;
end;
procedure TForm8.RefreshChannels;
var
I: integer;
begin
for I := 0 to noOfChannels - 1 do begin
with TTrackBar(channels.Objects[I]) do begin
OnChange := nil;
Position := round(GetChannelVolume(I) * 100);
OnChange := TrackBarChange;
end;
end;
if GetMute then
chkMute.Checked := true
else
chkMute.Checked := false;
masterVolume.OnChange := nil;
masterVolume.Position := round(GetMasterVolume() * 100);
masterVolume.OnChange := TrackBarChange;
end;
procedure TForm8.TrackBarChange(Sender: TObject);
begin
if TTrackBar(Sender).Tag = noOfChannels then begin
SetMasterVolume(TTrackBar(Sender).Position / 100);
exit;
end;
SetVolumeChannel(TTrackBar(Sender).Position / 100, TTrackBar(Sender).Tag);
end;
end.
答案 0 :(得分:3)
您的代码显而易见的问题是,您使用Double
作为浮点参数,而实际上它们是Single
。您无法决定在那里使用哪些类型。这是一个二进制接口,由接口的作者做出决定。将这些参数类型更改回Single
。
对于GetMute
方法,其参数应为BOOL
而不是Boolean
或Integer
。