2010-03-04 24 views
5

Tôi có một bàn phím mà không cần âm nhạc phím, để bật và giảm âm lượng, phát, dừng, v.v. của âm nhạc trong PC của tôi. Nếu bạn không hiểu, this là bàn phím của tôi và this thì không.Làm thế nào để kiểm soát chương trình khối lượng của máy tính của tôi?

Tôi muốn thực hiện, trong Windows và trong Delphi hoặc C#, một móc nối bàn phím để tạo tính năng âm lượng trong bàn phím của tôi, nhưng tôi không biết cách bật lên và xuống theo mã. Tôi đã thử các ví dụ thisthis, nhưng không hoạt động (tất cả trong Delphi, nhân tiện).

Bạn có biết cách tăng và giảm âm lượng theo mã không?

+0

Một số điều bạn có thể muốn đọc: http://www.codeguru.com/csharp/csharp/cs_graphics/sound/article.php/c10931 http://www.dreamincode.net/forums/ index.php?showtopic = 45693 –

Trả lời

6

Autohotkey sẽ thực hiện thủ thuật. Nó có lệnh "SoundSet" có thể điều chỉnh mức âm lượng/tắt tiếng cho tất cả các thiết bị âm thanh.

+0

Nó vẫn đòi hỏi một chút kịch bản - nếu bạn poke xung quanh, ai đó có thể đã tạo ra kịch bản autohotkey. –

+1

đẹp !! '^! NumpadSub :: Gửi {Volume_Up 10}' '^! NumpadAdd :: Gửi {Volume_Down 10}' '^! NumpadEnter :: Gửi {Volume_Mute}' – Joe

8

đang delphi sau.

keyhook tôi sẽ gửi một thông điệp tới hình thức chính của tôi với mã VK của chủ chốt trong 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; 

phạm vi khối lượng là 0 .. 65535; các giá trị ngoài băng được điều chỉnh âm thầm.

-

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

Đây là một bổ sung cho câu trả lời tuyệt vời glob của. SetMute/GetMute tờ khai chức năng phải sử dụng 32bit nguyên giá trị

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; 

Thay đổi SetMute và GetMute khai sử dụng các biến Integer và đúc Delphi boolean để nguyên.

phương pháp gọi là sau đó var iMute: Integer AudioEndVol.SetMute (Integer (CheckBox1.Checked), @GUID_NULL); AudioEndVol.GetMute (iMute);

Sử dụng bool không làm cho khayicon xác định trạng thái tắt tiếng đúng cách và bật tiếng không hoạt động chút nào. Tương tự với getmute, nó phải sử dụng tham số số nguyên 32 bit hoặc sắp xếp bộ nhớ bị hỏng một cách ngẫu nhiên. Tôi không hiểu một lý do để googled và tìm thấy một bài báo JEDI tuyệt vời.

Một số cuộc gọi win32 rất rất kén chọn về các giá trị bitwise, Delphi Bool/Boolean không luôn hoạt động tốt với các đối tác C. Sử dụng số nguyên 32 bit để biểu diễn biến C bool để khớp chính xác bitwise. Hầu hết các phương pháp win32 C không phải là nghiêm ngặt và làm việc tốt với bool/boolean. Chức năng MMDeviceAPI.SetMute cụ thể này là một trường hợp góc hiếm và các lập trình viên Delphi bị tấn công mạnh. http://blog.delphi-jedi.net/2008/09/25/bool-boolean-and-integer/

Các vấn đề liên quan