Прикручиваем мультимедиа-кнопки к клаве

для раздела Блоги
Начислено вознаграждение
Этот материал написан посетителем сайта, и за него начислено вознаграждение.
Есть в продаже отличные клавы, например эти две, но с существенным недостатком: отсутствием мультимедиа-кнопок. Видимо это сделано специально, что бы уменьшить размер клавы. ИМХО подход неправильный. Даже ыпл на своей компактной клаве нашла место для кнопок регулировки громкости, другие производители добавляют всего одну кнопку Fn, что тоже неплохо. В общем варианты есть, жаль что конструкторы ножничных клав не в теме. :(

Это недоразумение можно исправить с помощью гениальной проги Autohotkey. Какой только фигней на моем компе она не занималась… Вот сейчас за вечер добавил поддержку мультимедиа-кнопок для любой клавы.

Функции мм-кнопок будут выполнять обычные кнопки в комбинации с кнопкой Win. Конечно, придется обходить стороной комбинации, которые используются виндою, например Win+Home в семерке. Shift, Ctrl, Alt использовать нельзя, потому что будут конфликты с «горячими кнопками» в различных приложениях. Использовать несколько модификаторов что бы избежать конфликтов, например Alt+Shift+Кнопка, мне неудобно. Есть еще вариант заменить Win на ScrollLock (видел в проге, уже не помню какой), да тянуться далековато. Оставлю как запасной вариант.

Регулировка звука:
  • Win+Q — повышение громкости
  • Win+A — понижение громкости
  • Win+Z — приглушить звук
Эти комбинации используются наиболее часто, их можно быстро нажать левой рукой, не отрывая правую от крысы.

Но регулировать громкость кнопками неудобно. Идеальный вариант — крутилка (была на моей старой клаве A4 KX-5MU). Единственная крутилка, которая у меня есть — это колесо мыши. Поэтому:
  • Win+Колесо вверх — повышение громкости
  • Win+Колесо вниз — понижение громкости
Теоретически иногда могут быть ложные срабатывания, если колесо без щелчков и очень легко крутится. У меня все норм. Возможно, потом добавлю регулировку чувствительности и ускорения.

Дополнительный бонус вышеприведенных сочетаний в том, что они всегда регулируют только главную громкость звуковой карты независимо от запущенных приложений. Нажатие «настоящих» мм-кнопок некоторые проигрыватели перехватывают и изменяют свою громкость, что меня жутко раздражает. Теперь эти кривые проги не смогут пакостить, потому что регулировкой звука займется Проводник.

Управление проигрывателем:
  • Win+F1 — проигрывание/пауза
  • Win+F2 — остановка
  • Win+F3 — предыдущая композиция
  • Win+F4 — следующая композиция

У некоторых клав кнопка вызова куркулятора расположена рядом с блоком цифровых кнопок. Очень удобно. Поэтому:
  • Win+NumLock — запуск куркулятора
В качестве бонуса после запуска куркулятора всегда будет включен NumLock. Так же, если куркулятор уже запущен, то он будет активирован вместо запуска еще одной копии.

Ну и последняя кнопка, которая есть на многих клавах — это отправление винды в спячку. Я не использую спящий режим и гибернацию, поэтому комп полностью отключается. В скрипте несложно заменить выключение на спящий режим. Уже ощутили гибкость программных мм-кнопок? :)
  • Правая Win+Esc — выключение компьютера
Использование только правой кнопки Win предотвратит случайное нажатие.

Далее приведен текст скрипта. Как видите, он очень короткий. Сохраните его в кодировке Unicode в файле с расширением ahk. Установите Autohotkey Unicode последней версии по ссылке в начале этой заметки и пихайте скрипт в автозагрузку. В некоторых сетевых играх PunkBuster может ругаться на запущенный Autohotkey. Довольно редкий случай. Решение: скомпилируйте скрипт с помощью ahk2exe.exe (входит в состав Autohotkey) и запускайте вместо скрипта полученный exe-шник.

Дополнение от 12.08.2013
Добавлена вторая версия скрипта. Улучшения:
  • Добавлен индикатор громкости.
  • Добавлена настройка скорости регулировки громкости кнопками и колесом мыши.
  • Добавлен обход пары косяков Криватива.
  • Отключен автоповтор у кнопок управления проигрывателем.


;
; Version 2013.08.23
; Без индикатора громкости.
;
#Warn
#NoEnv
#KeyHistory 0
#SingleInstance FORCE
#UseHook
#NoTrayIcon
#MenuMaskKey VK07
ListLines OFF
SetBatchLines -1
Process PRIORITY,, HIGH

global CALCULATOR_EXECUTABLE   := "CALC.EXE"
global APPCOMMAND_VOLUME_MUTE  := 0x80000
global APPCOMMAND_VOLUME_DOWN  := 0x90000
global APPCOMMAND_VOLUME_UP    := 0xa0000

SendAppCommand(nCommand, fShell)
{
    hwnd := fShell ? DllCall("USER32.DLL\GetShellWindow", "UPTR") : WinExist("A")
    if (hwnd)
    {
        DllCall("USER32.DLL\SendMessageW", "UPTR", hwnd, "UINT", 0x0319, "PTR", 0, "PTR", nCommand) ; WM_APPCOMMAND
    }
}

HandlePlayerHotkey(strOriginalKey, strReplaceKey)
; Встроенное в autohotkey переназначение кнопок не используется, потому что нужно запретить автоповтор.
{
    SendInput {BLIND}{%strReplaceKey% DOWNTEMP}
    KeyWait %strOriginalKey%
    SendInput {BLIND}{%strReplaceKey% UP}
}

#Q::SendAppCommand(APPCOMMAND_VOLUME_UP, true)
#A::SendAppCommand(APPCOMMAND_VOLUME_DOWN, true)
#Z::SendAppCommand(APPCOMMAND_VOLUME_MUTE, true)
#WheelUp::SendAppCommand(APPCOMMAND_VOLUME_UP, true)
#WheelDown::SendAppCommand(APPCOMMAND_VOLUME_DOWN, true)
#F1::HandlePlayerHotkey("F1", "MEDIA_PLAY_PAUSE")
#F2::HandlePlayerHotkey("F2", "MEDIA_STOP")
#F3::HandlePlayerHotkey("F3", "MEDIA_PREV")
#F4::HandlePlayerHotkey("F4", "MEDIA_NEXT")

~#NumLock::
    Process EXIST, %CALCULATOR_EXECUTABLE%
    if (ErrorLevel)
    {
        WinActivate AHK_PID %ErrorLevel%
    }
    else
    {
        Run %CALCULATOR_EXECUTABLE%, %A_WinDir%\SYSTEM32
    }
    KeyWait NUMLOCK
    SetNumLockState ON
    return

>#Esc::Shutdown 8





реклама

; ; Version 2013.08.23 ; С индикатором громкости. ; #Warn #NoEnv #KeyHistory 0 #SingleInstance FORCE #NoTrayIcon #UseHook #MenuMaskKey VK07 ListLines OFF SetBatchLines -1 Process PRIORITY,, HIGH global VOLUME_STEP_FIRST := 2 global VOLUME_STEP_NEXT := 2 global VOLUME_STEP_WHEEL := 4 global VOLUME_INTERVAL_FIRST := 200 global VOLUME_INTERVAL_NEXT := 40 global VOLUME_CRIVATIVE_STEP := 1 ; 0.3 global VOLUME_CRIVATIVE_FLOOR := 0 ; 4.2 global INDICATOR_LOCATION_X := 80 global INDICATOR_LOCATION_Y := 80 global INDICATOR_SHOW_TIME := 1000 global CALCULATOR_EXECUTABLE := "CALC.EXE" global g_pIDirectDraw7 := 0 ; #Warn global g_nVolume := -1, g_fMute := -1 global g_hwndGui := 0, g_hwndProgress, g_idProgress, g_idImage, g_fThemed, g_hTheme InitInstance() return InitInstance() {     DllCall("KERNEL32.DLL\LoadLibraryW", "WSTR", "DDRAW.DLL", "UPTR")     VarSetCapacity(IID_IDirectDraw7, 16)     DllCall("OLE32.DLL\CLSIDFromString", "WSTR", "{15E65EC0-3B9C-11D2-B92F-00609797EA5B}", "UPTR", &IID_IDirectDraw7) ; Указать DDCREATE_EMULATIONONLY вместо 0, что бы создание IDirectDraw7 не потребляло 20 MiB оперативной памяти. DllCall("DDRAW.DLL\DirectDrawCreateEx", "UPTR", 2, "UPTR*", g_pIDirectDraw7, "UPTR", &IID_IDirectDraw7, "UPTR", 0)     ; Если тема оформления отлична от windows classic, то у виндового progress bar появляется анимация, отключить     ; которую простыми способами нельзя. Придется рисовать progress bar самому.     DllCall("KERNEL32.DLL\LoadLibraryW", "WSTR", "UXTHEME.DLL", "UPTR")     OnMessage(0x2B, "DrawIndicator") ; WM_DRAWITEM } IsNotificationsAllowed() ; Вывод окна, даже неактивного, конфликтует с полноэкранными приложениями Direct3D. SHQueryUserNotificationState() по ; непонятной причине не возвращает QUNS_RUNNING_D3D_FULL_SCREEN. IDirectDraw7::TestCooperativeLevel() возвращает ; DDERR_EXCLUSIVEMODEALREADYSET если активно полноэкранное Direct3D или OpenGL приложение, а так же если неактивна ; сессия пользователя (Win+L, Alt+Ctrl+Del, FUS). Проверялось в Windows 7. {     ; IDirectDraw7::TestCooperativeLevel() != DDERR_EXCLUSIVEMODEALREADYSET     return DllCall(NumGet(NumGet(g_pIDirectDraw7 + 0) + 26 * A_PtrSize), "UPTR", g_pIDirectDraw7) != -2005532091 } ShowIndicator(nOldVolume, fOldMute) { if (g_hwndGui) { UpdateIndicator(nOldVolume, fOldMute)     }     else if (IsNotificationsAllowed())     { g_fThemed := DllCall("UXTHEME.DLL\IsAppThemed") Gui -CAPTION +BORDER +ALWAYSONTOP +DISABLED +E0x8000000 HWNDg_hwndGui ; WS_EX_NOACTIVATE DllCall("USER32.DLL\SetClassLongW", "UPTR", g_hwndGui, "INT", -26, "INT" , DllCall("USER32.DLL\GetClassLongW", "UPTR", g_hwndGui, "INT", -26) | 0x20000) ; CS_DROPSHADOW if (g_fThemed) { Gui ADD, TEXT, W16 H150 X5 Y5 +0x0D HWNDg_hwndProgress Vg_idProgress ; SS_OWNERDRAW g_hTheme := DllCall("UXTHEME.DLL\OpenThemeData", "UPTR", g_hwndProgress, "WSTR", "PROGRESS", "UPTR") DllCall("UXTHEME.DLL\BufferedPaintInit") } else { Gui ADD, PROGRESS, W16 H150 X5 Y5 +VERTICAL -SMOOTH HWNDg_hwndProgress Vg_idProgress SendMessage 0x401,, 0x00640000 | VOLUME_CRIVATIVE_FLOOR,, AHK_ID %g_hwndProgress% ; PBM_SETRANGE VOLUME_CRIVATIVE_FLOOR..100 } Gui ADD, PICTURE, W16 H16 X5 Y160 Vg_idImage SysGet nMwa, MONITORWORKAREA Gui SHOW, % "NOACTIVATE W26 H181" . " X" . (nMwaRight  - (INDICATOR_LOCATION_X +  26) * A_ScreenDPI / 96) . " Y" . (nMwaBottom - (INDICATOR_LOCATION_Y + 181) * A_ScreenDPI / 96) ; BUG OnMessage() по непонятной причине не посылает сообщение во время выполнения Gui SHOW, ; поэтому g_hwndProgress не прорисовывается. Обновляем окно уже после Gui SHOW. Это может ; привести к небольшому мерцанию. UpdateIndicator(-1, -1) } } DestroyIndicator() {     if (g_hwndGui)     { ; На тень анимация не действует, но с короткой длительностью этого не заметно. DllCall("USER32.DLL\AnimateWindow", "UPTR", g_hwndGui, "UINT", 80, "UINT", 0x90000) ; AW_BLEND | AW_HIDE if (g_fThemed) { DllCall("UXTHEME.DLL\BufferedPaintUnInit") DllCall("UXTHEME.DLL\CloseThemeData", "UPTR", g_hTheme) } Gui DESTROY g_hwndGui := 0     } } UpdateIndicator(nOldVolume, fOldMute) {     if (g_nVolume == nOldVolume && g_fMute == fOldMute)     { return     }     if (g_fMute != fOldMute)     { if (g_fMute) { GuiControl,, g_idImage, *ICON3 %A_WinDir%\SYSTEM32\SNDVOL.EXE if (!g_fThemed) { SendMessage 0x410, 2,,, AHK_ID %g_hwndProgress% ; PBM_SETSTATE PBST_ERROR } } else { GuiControl,, g_idImage, *ICON2 %A_WinDir%\SYSTEM32\SNDVOL.EXE if (!g_fThemed) { SendMessage 0x410, 1,,, AHK_ID %g_hwndProgress% ; PBM_SETSTATE PBST_NORMAL } }     }     if (g_nVolume != nOldVolume && !g_fThemed)     { GuiControl,, g_idProgress, %g_nVolume% if (g_fMute) { ; HACK В состоянии PBST_ERROR по непонятной причине первое PBM_SETPOS не срабатывает. GuiControl,, g_idProgress, %g_nVolume% }     }     if (g_fThemed)     { ; GuiControl MOVEDRAW не подходит, потому что посылает приводящий к мерцанию WM_ERASEBKGND. WinSet REDRAW,, AHK_ID %g_hwndProgress%     } } DrawIndicator(wParam, lParam) {     hdcScreen := NumGet(lParam + 16 + A_PtrSize + A_PtrSize)     prcItem := lParam + 16 + A_PtrSize + A_PtrSize + A_PtrSize     hdcBuffer := 0 ; #Warn     hBuffer := DllCall("UXTHEME.DLL\BeginBufferedPaint", "UPTR", hdcScreen, "UPTR", prcItem, "INT", 0, "UPTR", 0, "UPTR*", hdcBuffer) ; BPBF_COMPATIBLEBITMAP     if (DllCall("UXTHEME.DLL\IsThemeBackgroundPartiallyTransparent", "UPTR", g_hTheme, "INT", 12, "INT", 1)) ; PP_TRANSPARENTBARVERT, PBBVS_NORMAL     { DllCall("UXTHEME.DLL\DrawThemeParentBackground", "UPTR", g_hwndProgress, "UPTR", hdcBuffer, "UPTR", prcItem)     }     DllCall("UXTHEME.DLL\DrawThemeBackground", "UPTR", g_hTheme, "UPTR", hdcBuffer, "INT", 12, "INT", 1, "UPTR", prcItem, "UPTR", 0) ; PP_TRANSPARENTBARVERT, PBBVS_NORMAL     NumPut(NumGet(prcItem + 12, "INT") * (100 - g_nVolume) / (100 - VOLUME_CRIVATIVE_FLOOR), prcItem + 4, "INT")     DllCall("UXTHEME.DLL\DrawThemeBackground", "UPTR", g_hTheme, "UPTR", hdcBuffer, "INT", 6, "INT", g_fMute + 1, "UPTR", prcItem, "UPTR", 0) ; PP_FILLVERT, PBFS_NORMAL / PBFS_ERROR     DllCall("UXTHEME.DLL\EndBufferedPaint", "UPTR", hBuffer, "INT", 1)     return 1 } SetMasterVolume(nValue) {     if (g_nVolume < 0)     { SoundGet g_nVolume SoundGet g_fMute,, MUTE if (g_nVolume < VOLUME_CRIVATIVE_FLOOR) { g_nVolume := VOLUME_CRIVATIVE_FLOOR } g_fMute := g_fMute != "Off"     }          nOldVolume := g_nVolume, fOldMute := g_fMute     if (nValue == 0)     { g_fMute := !g_fMute     }     else     { ; Пока и линейный сгодится. nStepFactor := (1 - VOLUME_CRIVATIVE_STEP) * g_nVolume / 100 + VOLUME_CRIVATIVE_STEP g_nVolume += nValue * nStepFactor if (g_nVolume < VOLUME_CRIVATIVE_FLOOR) { g_nVolume := VOLUME_CRIVATIVE_FLOOR } if (g_nVolume > 100) { g_nVolume := 100 } if (nValue > 0) { g_fMute := false }     }     ShowIndicator(nOldVolume, fOldMute)     SetTimer Timer_DestroyIndicator, % -INDICATOR_SHOW_TIME     if (g_nVolume != nOldVolume)     { SoundSet g_nVolume     }     if (g_fMute != fOldMute)     { SoundSet g_fMute,, MUTE     }     return Timer_DestroyIndicator:     Critical     DestroyIndicator()     g_nVolume := -1, g_fMute := -1     return } HandleVolumeHotkey(nValue, strKey := "", nFirstInterval := 0, nNextInterval := 0, nNextStep := 0) {     ; Если нажато несколько кнопок управлением громкостью, то обрабатываться будет только первая из них.     static fBusy := false     if (!fBusy)     { fBusy := true SetMasterVolume(nValue) if (strKey) { if (!nFirstInterval) { KeyWait % strKey } else { KeyWait % strKey, % "T" . (nFirstInterval / 1000) if (ErrorLevel) { SetTimer Timer_ChangeVolume, % nNextInterval gosub Timer_ChangeVolume KeyWait % strKey SetTimer Timer_ChangeVolume, OFF } } } fBusy := false     }     return Timer_ChangeVolume:     SetMasterVolume(nNextStep)     return } HandlePlayerHotkey(strOriginalKey, strReplaceKey) ; Встроенное в autohotkey переназначение кнопок не используется, потому что нужно запретить автоповтор. { SendInput {BLIND}{%strReplaceKey% DOWNTEMP} KeyWait %strOriginalKey% SendInput {BLIND}{%strReplaceKey% UP} } #Q::HandleVolumeHotkey(VOLUME_STEP_FIRST, "Q", VOLUME_INTERVAL_FIRST, VOLUME_INTERVAL_NEXT, VOLUME_STEP_NEXT) #A::HandleVolumeHotkey(-VOLUME_STEP_FIRST, "A", VOLUME_INTERVAL_FIRST, VOLUME_INTERVAL_NEXT, -VOLUME_STEP_NEXT) #Z::HandleVolumeHotkey(0, "Z") #WheelUp::HandleVolumeHotkey(VOLUME_STEP_WHEEL) #WheelDown::HandleVolumeHotkey(-VOLUME_STEP_WHEEL) #F1::HandlePlayerHotkey("F1", "MEDIA_PLAY_PAUSE") #F2::HandlePlayerHotkey("F2", "MEDIA_STOP") #F3::HandlePlayerHotkey("F3", "MEDIA_PREV") #F4::HandlePlayerHotkey("F4", "MEDIA_NEXT") ~#NUMLOCK::     Process EXIST, %CALCULATOR_EXECUTABLE%     if (ErrorLevel)     { WinActivate AHK_PID %ErrorLevel%     }     else     { Run %CALCULATOR_EXECUTABLE%, %A_WinDir%\SYSTEM32     }     KeyWait NUMLOCK     SetNumLockState ON     return >#ESC::Shutdown 8
Подпишитесь на наш канал в Яндекс.Дзен или telegram-канал @overclockers_news - это удобные способы следить за новыми материалами на сайте. С картинками, расширенными описаниями и без рекламы.
Оценитe материал
рейтинг: 1.0 из 5
голосов: 1

Возможно вас заинтересует

Популярные новости

Сейчас обсуждают