Прикручиваем мультимедиа-кнопки к клаве
реклама
Это недоразумение можно исправить с помощью гениальной проги 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
реклама
Теги
Лента материалов
Соблюдение Правил конференции строго обязательно!
Флуд, флейм и оффтоп преследуются по всей строгости закона!
Комментарии, содержащие оскорбления, нецензурные выражения (в т.ч. замаскированный мат), экстремистские высказывания, рекламу и спам, удаляются независимо от содержимого, а к их авторам могут применяться меры вплоть до запрета написания комментариев и, в случае написания комментария через социальные сети, жалобы в администрацию данной сети.
Сейчас обсуждают