2010-03-04 7 views
5

У меня есть клавиатура без музыка клавиши, которые для включения и выключения громкости, воспроизведения, остановки и т. Д. Музыки на моем ПК. Если вы не понимаете, this - это моя клавиатура и this нет.Как программно контролировать объем моего компьютера?

Я хочу реализовать в Windows и Delphi или C# клавиатурный крючок, чтобы создать функцию тома на моей клавиатуре, но я не знаю, как повернуть ее вверх и вниз по коду. Я пробовал this и this примеров, но не работал (все в Delphi, между прочим).

Знаете ли вы, как увеличивать и уменьшать объем кода?

+0

Некоторые статьи вы можете прочитать: http://www.codeguru.com/csharp/csharp/cs_graphics/sound/article.php/c10931 http://www.dreamincode.net/forums/ index.php?showtopic = 45693 –

ответ

6

Autohotkey будет делать трюк. Он имеет команду «SoundSet», которая может регулировать уровни громкости/отключения звука для всех аудиоустройств.

+0

Он по-прежнему требует немного сценариев - если вы ткнете, кто-то, скорее всего, уже создал сценарий autohotkey. –

+1

приятно !! '^! NumpadSub :: Отправить {Volume_Up 10}' '^! NumpadAdd :: Отправить {Volume_Down 10}' '^! NumpadEnter :: Отправить {Volume_Mute}' – Joe

8

код Дельфы следующим образом.

мой keyhook посылает сообщение к моей главной форме с ключа VK кода в LPARAM,

procedure TmainFrm.keyHook(var msg: TMessage); 
begin 
    case msg.LParam of 
    VK_VOLUME_UP : g_mixer.volume := g_mixer.volume + 2048; 
    VK_VOLUME_DOWN: g_mixer.volume := g_mixer.volume - 2048; 
    VK_VOLUME_MUTE: g_mixer.muted := not g_mixer.muted; 
    end; 
end; 

диапазон громкости 0 .. 65535; внеполосные значения тихо корректируются.

-

unit Mixer; 

interface 

type 

    Tmixer = class 
    protected 
    function getMute: boolean; virtual; abstract; 
    function getVolume: integer; virtual; abstract; 
    procedure setVolume(Value: integer); virtual; abstract; 
    procedure setMute(Value: boolean); virtual; abstract; 
    public 
    property volume: integer read getVolume write setVolume; 
    property muted: boolean read getMute write setMute; 
    end; 

function g_mixer: Tmixer; 

implementation 

uses 
    Windows, MMSystem, MMDevApi_tlb, ComObj, ActiveX, SysUtils; 

// --------------------------------------------------------------------------- 

type 

    TxpMixer = class(Tmixer) 
    private 
    Fmxct: integer; 
    Fmixer: HMIXER; 
    procedure chk(r: MMRESULT); 
    protected 
    function getMute: boolean; override; 
    function getVolume: integer; override; 
    procedure setVolume(Value: integer); override; 
    procedure setMute(Value: boolean); override; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    end; 

    TvistaMixer = class(Tmixer) 
    private 
    FmmDev: IMMDevice; 
    FmmDevEnum: IMMDeviceEnumerator; 
    FmmEndpoint: IMMAudioEndpointVolume; 
    protected 
    function getMute: boolean; override; 
    function getVolume: integer; override; 
    procedure setVolume(Value: integer); override; 
    procedure setMute(Value: boolean); override; 
    public 
    constructor Create; 
    end; 

// --------------------------------------------------------------------------- 

var 
    _g_mixer: Tmixer; 

function g_mixer: Tmixer; 
var 
    VerInfo: TOSVersioninfo; 
begin 
    if (_g_mixer = nil) then 
    begin 
    VerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); 
    GetVersionEx(VerInfo); 
    if (VerInfo.dwMajorVersion >= 6) then 
     _g_mixer := TvistaMixer.Create 
    else 
     _g_mixer := TxpMixer.Create; 
    end; 
    result := _g_mixer; 
end; 

// --------------------------------------------------------------------------- 

{ TxpMixer } 

procedure TxpMixer.chk(r: MMRESULT); 
var 
    s: string; 
begin 
    if (r = MMSYSERR_NOERROR) then 
    exit; 
    setLength(s, MMSystem.MAXERRORLENGTH + 1); 
    waveOutGetErrorText(r, @s[1], MMSystem.MAXERRORLENGTH); 
    raise Exception.Create(StrPas(pChar(s))); 
end; 

// --------------------------------------------------------------------------- 

constructor TxpMixer.Create; 
begin 
    Fmxct := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; 
    chk(mixerOpen(@Fmixer, 0, 0, 0, 0)); 
end; 

// --------------------------------------------------------------------------- 

destructor TxpMixer.Destroy; 
begin 
    if (Fmixer <> 0) then 
    mixerClose(Fmixer); 
    inherited; 
end; 

// --------------------------------------------------------------------------- 

function TxpMixer.getMute: boolean; 
var 
    MasterMute: TMixerControl; 
    Details: TMixerControlDetails; 
    BoolDetails: TMixerControlDetailsBoolean; 
    Line: TMixerLine; 
    Controls: TMixerLineControls; 
begin 
    ZeroMemory(@Line, SizeOf(Line)); 
    Line.cbStruct := SizeOf(Line); 
    Line.dwComponentType := Fmxct; 
    chk(mixerGetLineInfo(0, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE)); 

    ZeroMemory(@Controls, SizeOf(Controls)); 
    Controls.cbStruct := SizeOf(Controls); 
    Controls.dwLineID := Line.dwLineID; 
    Controls.cControls := 1; 
    Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_MUTE; 
    Controls.cbmxctrl := SizeOf(MasterMute); 
    Controls.pamxctrl := @MasterMute; 
    chk(mixerGetLineControls(0, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE)); 

    Details.cbStruct := SizeOf(Details); 
    Details.dwControlID := MasterMute.dwControlID; 
    Details.cChannels := 1; 
    Details.cMultipleItems := 0; 
    Details.cbDetails := SizeOf(BoolDetails); 
    Details.paDetails := @BoolDetails; 
    chk(mixerGetControlDetails(0, @Details, MIXER_GETCONTROLDETAILSF_VALUE)); 

    result := BoolDetails.fValue <> 0; 
end; 

// --------------------------------------------------------------------------- 

function TxpMixer.getVolume: integer; 
var 
    Line: TMixerLine; 
    Controls: TMixerLineControls; 
    MasterVolume: TMixerControl; 
    Details: TMixerControlDetails; 
    UnsignedDetails: TMixerControlDetailsUnsigned; 
begin 
    ZeroMemory(@Line, SizeOf(Line)); 
    Line.cbStruct := SizeOf(Line); 
    Line.dwComponentType := Fmxct; 
    chk(mixerGetLineInfo(Fmixer, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE)); 
    ZeroMemory(@Controls, SizeOf(Controls)); 
    Controls.cbStruct := SizeOf(Controls); 
    Controls.dwLineID := Line.dwLineID; 
    Controls.cControls := 1; 
    Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME; 
    Controls.cbmxctrl := SizeOf(MasterVolume); 
    Controls.pamxctrl := @MasterVolume; 
    chk(mixerGetLineControls(Fmixer, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE)); 

    details.cbStruct := SizeOf(Details); 
    details.dwControlID := MasterVolume.dwControlID; 
    details.cChannels := 1; 
    details.cMultipleItems := 0; 
    details.cbDetails := SizeOf(UnsignedDetails); 
    details.paDetails := @UnsignedDetails; 
    chk(mixerGetControlDetails(Fmixer, @Details, MIXER_GETCONTROLDETAILSF_VALUE)); 
    result := UnsignedDetails.dwValue; 
end; 

// --------------------------------------------------------------------------- 

procedure TxpMixer.setMute(Value: boolean); 
var 
    Line: TMixerLine; 
    Controls: TMixerLineControls; 
    MasterMute: TMixerControl; 
    Details: TMixerControlDetails; 
    BoolDetails: TMixerControlDetailsBoolean; 
begin 
    ZeroMemory(@Line, SizeOf(Line)); 
    Line.cbStruct := SizeOf(Line); 
    Line.dwComponentType := Fmxct; 
    chk(mixerGetLineInfo(Fmixer, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE)); 
    ZeroMemory(@Controls, SizeOf(Controls)); 
    Controls.cbStruct := SizeOf(Controls); 
    Controls.dwLineID := Line.dwLineID; 
    Controls.cControls := 1; 
    Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_MUTE; 
    Controls.cbmxctrl := SizeOf(masterMute); 
    Controls.pamxctrl := @masterMute; 
    chk(mixerGetLineControls(Fmixer, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE)); 

    details.cbStruct := SizeOf(Details); 
    details.dwControlID := MasterMute.dwControlID; 
    details.cChannels := 1; 
    details.cMultipleItems := 0; 
    details.cbDetails := SizeOf(BoolDetails); 
    details.paDetails := @BoolDetails; 
    mixerGetControlDetails(0, @Details, MIXER_GETCONTROLDETAILSF_VALUE); 
    if (Value) then 
    BoolDetails.fValue := 1 
    else 
    BoolDetails.fValue := 0; 

    chk(mixerSetControlDetails(0, @Details, MIXER_SETCONTROLDETAILSF_VALUE)); 
end; 

// --------------------------------------------------------------------------- 

procedure TxpMixer.setVolume(Value: integer); 
var 
    Line: TMixerLine; 
    Controls: TMixerLineControls; 
    MasterVolume: TMixerControl; 
    Details: TMixerControlDetails; 
    UnsignedDetails: TMixerControlDetailsUnsigned; 
begin 
    if (value < 0) then 
    value := 0; 
    if (value > 65535) then 
    value := 65535; 

    ZeroMemory(@Line, SizeOf(Line)); 
    Line.cbStruct := SizeOf(Line); 
    Line.dwComponentType := Fmxct; 
    chk(mixerGetLineInfo(Fmixer, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE)); 
    ZeroMemory(@Controls, SizeOf(Controls)); 
    Controls.cbStruct := SizeOf(Controls); 
    Controls.dwLineID := Line.dwLineID; 
    Controls.cControls := 1; 
    Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME; 
    Controls.cbmxctrl := SizeOf(MasterVolume); 
    Controls.pamxctrl := @MasterVolume; 
    chk(mixerGetLineControls(Fmixer, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE)); 

    details.cbStruct := SizeOf(Details); 
    details.dwControlID := MasterVolume.dwControlID; 
    details.cChannels := 1; 
    details.cMultipleItems := 0; 
    details.cbDetails := SizeOf(UnsignedDetails); 
    details.paDetails := @UnsignedDetails; 
    UnsignedDetails.dwValue := Value; 
    chk(mixerSetControlDetails(Fmixer, @Details, MIXER_SETCONTROLDETAILSF_VALUE)); 
end; 

// --------------------------------------------------------------------------- 

{ TvistaMixer } 

constructor TvistaMixer.Create; 
begin 
    CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, FmmDevEnum); 
    FmmDevEnum.GetDefaultAudioEndpoint(eRender, eMultimedia, FmmDev); 
    FmmDev.Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, nil, FmmEndpoint); 
end; 

// --------------------------------------------------------------------------- 

function TvistaMixer.getMute: boolean; 
begin 
    FmmEndpoint.GetMute(Result); 
end; 

// --------------------------------------------------------------------------- 

function TvistaMixer.getVolume: integer; 
var 
    VolLevel: Single; 
begin 
    FmmEndpoint.GetMasterVolumeLevelScalar(VolLevel); 
    result := Round(VolLevel * 65535); 
end; 

// --------------------------------------------------------------------------- 

procedure TvistaMixer.setMute(Value: boolean); 
begin 
    FmmEndpoint.SetMute(Value, nil); 
end; 

// --------------------------------------------------------------------------- 

procedure TvistaMixer.setVolume(Value: integer); 
var 
    fValue: Single; 
begin 
    if (value < 0) then 
    value := 0; 
    if (value > 65535) then 
    value := 65535; 
    fValue := Value/65535; 
    FmmEndpoint.SetMasterVolumeLevelScalar(fValue, nil); 
end; 

// --------------------------------------------------------------------------- 

end. 

-

unit MMDevApi_tlb; 

interface 
    uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj; 
const 
    // TypeLibrary Major and minor versions 

    CLSID_MMDeviceEnumerator: 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}'; 
    GUID_NULL: TGUID        = '{00000000-0000-0000-0000-000000000000}'; 

    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 GetMasterVolumeLevelScalar(out fLevel: single):Integer; stdcall; 
    Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall; 
    Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: single; pguidEventContext: TGUID):Integer; stdcall; 
    Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall; 
    Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : 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: TGUID) :Integer; stdcall; 
    Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall; 
    Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall; 
    Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall; 
    end; 

    IPropertyStore = interface(IUnknown) 
    end; 

type 
    IMMDevice = interface(IUnknown) 
    ['{D666063F-1587-4E43-81F1-B948E807363F}'] 
    Function Activate( const refId :TGUID; 
         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. 
0

Это дополнение к отличному ответу Глоб в. объявления функций SetMute/GetMute должны использовать 32-разрядные целые значения

unit MMDevApi_tlb; 
const 
    DEVICE_STATE_ACTIVE  = $00000001; 
    DEVICE_STATE_UNPLUGGED = $00000002; 
    DEVICE_STATE_NOTPRESENT = $00000004; 
    DEVICE_STATEMASK_ALL  = $00000007; 

    IMMAudioEndpointVolume = interface(IUnknown) 
    ['{5CDF2C82-841E-4546-9722-0CF74078229A}'] 
    Function SetMute(iMute: Integer; pguidEventContext: PGUID) :Integer; stdcall; 
    Function GetMute(out iMute: Integer) :Integer; stdcall; 

Изменение SetMute и GetMute декларацию использовать переменные Integer и ввергнуть Delphi логическое значение в целое.

вызовы методов затем вар IMUTE: Целое число AudioEndVol.SetMute (целое число (CheckBox1.Checked), @GUID_NULL); AudioEndVol.GetMute (iMute);

Использование bool не приводит к тому, что лотокфон неправильно определяет состояние звука и включение звука не работает вообще. То же самое относится к getmute, он должен использовать 32-битный целочисленный параметр или выравнивание памяти случайным образом повреждено. Я не понимал, что такое рассуждение было искаженным и нашел отличную статью JEDI.

Некоторые вызовы win32 очень разборчивы по поразрядным значениям, Delphi Bool/Boolean не всегда хорошо сочетаются с C-коллегами. Используйте 32-битное целое число для представления переменной C bool с точным поразрядным совпадением. Большинство методов win32 C не так строги и отлично работают с bool/boolean. Эта конкретная функция MMDeviceAPI.SetMute является редким угловым случаем, и программисты Delphi сильно пострадали. http://blog.delphi-jedi.net/2008/09/25/bool-boolean-and-integer/

Смежные вопросы