Прикручиваем мультимедиа-кнопки к клаве
Есть в продаже отличные клавы, например <a href="http://www.fcenter.ru/products.shtml?eshop/act=h:a:0:18:a:a:a:1:a:3:25:r:2:buyperson:d582_d39&oper=94508::::" rel="nofollow" >эти</a> <a href="http://www.fcenter.ru/products.shtml?eshop/act=h:a:0:18:a:a:a:1:a:3:25:r:2:buyperson:d582_d39&oper=94515::::" rel="nofollow" >две</a>, но с существенным недостатком: отсутствием мультимедиа-кнопок. Видимо это сделано специально, что бы уменьшить размер клавы. ИМХО подход неправильный. Даже ыпл на своей компактной клаве нашла место для кнопок регулировки громкости, другие производители добавляют всего одну кнопку Fn, что тоже неплохо. В общем варианты есть, жаль что конструкторы ножничных клав не в теме. :(<br/>
<br/>
Это недоразумение можно исправить с помощью гениальной проги <a href="http://www.autohotkey.com/" rel="nofollow" >Autohotkey</a>. Какой только фигней на моем компе она не занималась… Вот сейчас за вечер добавил поддержку мультимедиа-кнопок для любой клавы.<br/>
Есть в продаже отличные клавы, например эти две, но с существенным недостатком: отсутствием мультимедиа-кнопок. Видимо это сделано специально, что бы уменьшить размер клавы. ИМХО подход неправильный. Даже ыпл на своей компактной клаве нашла место для кнопок регулировки громкости, другие производители добавляют всего одну кнопку Fn, что тоже неплохо. В общем варианты есть, жаль что конструкторы ножничных клав не в теме. :(
Это недоразумение можно исправить с помощью гениальной проги Autohotkey. Какой только фигней на моем компе она не занималась… Вот сейчас за вечер добавил поддержку мультимедиа-кнопок для любой клавы.
Функции мм-кнопок будут выполнять обычные кнопки в комбинации с кнопкой Win. Конечно, придется обходить стороной комбинации, которые используются виндою, например Win+Home в семерке. Shift, Ctrl, Alt использовать нельзя, потому что будут конфликты с «горячими кнопками» в различных приложениях. Использовать несколько модификаторов что бы избежать конфликтов, например Alt+Shift+Кнопка, мне неудобно. Есть еще вариант заменить Win на ScrollLock (видел в проге, уже не помню какой), да тянуться далековато. Оставлю как запасной вариант.
Регулировка звука:
Но регулировать громкость кнопками неудобно. Идеальный вариант — крутилка (была на моей старой клаве A4 KX-5MU). Единственная крутилка, которая у меня есть — это колесо мыши. Поэтому:
Дополнительный бонус вышеприведенных сочетаний в том, что они всегда регулируют только главную громкость звуковой карты независимо от запущенных приложений. Нажатие «настоящих» мм-кнопок некоторые проигрыватели перехватывают и изменяют свою громкость, что меня жутко раздражает. Теперь эти кривые проги не смогут пакостить, потому что регулировкой звука займется Проводник.
Управление проигрывателем:
У некоторых клав кнопка вызова куркулятора расположена рядом с блоком цифровых кнопок. Очень удобно. Поэтому:
Ну и последняя кнопка, которая есть на многих клавах — это отправление винды в спячку. Я не использую спящий режим и гибернацию, поэтому комп полностью отключается. В скрипте несложно заменить выключение на спящий режим. Уже ощутили гибкость программных мм-кнопок? :)
Далее приведен текст скрипта. Как видите, он очень короткий. Сохраните его в кодировке Unicode в файле с расширением ahk. Установите Autohotkey Unicode последней версии по ссылке в начале этой заметки и пихайте скрипт в автозагрузку. В некоторых сетевых играх PunkBuster может ругаться на запущенный Autohotkey. Довольно редкий случай. Решение: скомпилируйте скрипт с помощью ahk2exe.exe (входит в состав Autohotkey) и запускайте вместо скрипта полученный exe-шник.
Дополнение от 12.08.2013
Добавлена вторая версия скрипта. Улучшения:
Это недоразумение можно исправить с помощью гениальной проги 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 — запуск куркулятора
Ну и последняя кнопка, которая есть на многих клавах — это отправление винды в спячку. Я не использую спящий режим и гибернацию, поэтому комп полностью отключается. В скрипте несложно заменить выключение на спящий режим. Уже ощутили гибкость программных мм-кнопок? :)
- Правая Win+Esc — выключение компьютера
Далее приведен текст скрипта. Как видите, он очень короткий. Сохраните его в кодировке 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
Теги
Лента материалов
Правила размещения комментариев
Соблюдение Правил конференции строго обязательно!
Флуд, флейм и оффтоп преследуются по всей строгости закона!
Комментарии, содержащие оскорбления, нецензурные выражения (в т.ч. замаскированный мат), экстремистские высказывания, рекламу и спам, удаляются независимо от содержимого, а к их авторам могут применяться меры вплоть до запрета написания комментариев и, в случае написания комментария через социальные сети, жалобы в администрацию данной сети.


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