Тема: AutoHotkey: Управление окнами с помощью горячих клавиш
Выкладываю фрагмент постоянно загруженного у меня скрипта, который помогает управлять разными окнами с клавиатуры: закрывать (разными способами), закрывать без сохранения (т.е. автоматически подтверждать, что сохранять изменения не надо), сворачивать/разворачивать, разворачивать(максимизировать)/восстанавливать, назначать/снимать "поверх всех". Сюда же я добавил скрипт из справки к AutoHotkey, позволяющий перетаскивать окно за любую его часть (EWD). Пользуюсь всем этим уже пару лет, и если оказываюсь где-то, где я еще не успел загрузить свой базовый скрипт, то некоторое время (недолгое, к счастью) в растерянности пытаюсь понять: "что это за странные глюки винды ". В общем, удобные фишки. Разумеется, изменить горячие клавиши или прочую мелочь под свои желания не составит у вас труда. Найдете способы улучшить - поделитесь, буду благодарен.
;*****************************************************************************
; AutoHotkey Version: 1.0.41.01+
; Автор: Androgen Belkin
; Имя скрипта: ControlsWinows.ahk (v.1.3)
;*****************************************************************************
; Управление окнами с помощью горячих клавиш.
;*****************************************************************************
#NoEnv ; запрещаем имена переменных как у переменных окружения (повышаем производительность скрипта)
;~ #NoTrayIcon ; не отображать иконку скрипта в трее
SendMode Input ; новый режим высылки без задержки и повышенной надежности
SetTitleMatchMode, 2 ; сравнивать с любой частью заголовка окна
; ========== ЗАКРЫТИЕ ПО ESCAPE (ТОЛЬКО УКАЗАННЫХ ОКОН) ===============
~ESC:: ; Escape - закрытие некоторых окон (справка, консоль, проводник, блокнот и др.)
;-----------------------------------------------------------------------------
If EWD_Work = 1 ; если сейчас работает перемещение окна с помощью мыши (EWD), то...
Return ; закончить обработку горячей клавиши (т.к. Escape назначена в EWD для отмены перемещения окна)
WinGetActiveTitle, Win_To_Close_Title ; сохранить заголовок в переменной
WinGetClass, Win_To_Close_Class, A ; получить класс активного окна
Win_To_Close = HH Parent|ConsoleWindowClass|ExploreWClass|CabinetWClass|NativeHWNDHost|Notepad|AutoHotkey2|TWhatNodeFrm|RegEdit_RegEdit ; список классов закрываемых окон
; 1 справка, 2 консоль, 3 проводник, 4 проводник(другой), 5 установка и удаление программ, 6 блокнот, 7 список горячих клавиш, 8 окно выбора ключей в ART, RegEdit
Loop, parse, Win_To_Close, | ; обработать список окон (разделитель - "|")
{
If Win_To_Close_Class = %A_LoopField% ; если текущее окно - из списка, то...
{
WinClose, ahk_class %Win_To_Close_Class% ; закрыть окно
KeyWait, ESC ; ожидать пока клавиша не будет отпущена (чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши
}
}
; ---------- дополнительный список окон, которые нужно закрыть ---------------
; === WinClose, WinKill, PostMessage - не закрывает неспецифицированные ahk_class #32770 (например, окно FreeMemory) ===
; указать через запятую фрагменты заголовков окон, которые нужно закрыть (пробелов после запятой не делать)
If Win_To_Close_Title contains FuncPopUp,- PromtX,- X-Translator PLATINUM,FreeMemory,FreeRAM XP Pro ; список фрагментов заголовков окон
Send !{F4} ; закрыть окно по заголовку
If Win_To_Close_Title = Media Library ; если окно - Media Library (Winamp)
Send !{sc026} ; закрыть окно Media Library по горячей клавише Alt+L
KeyWait, ESC ; ожидать пока клавиша не будет отпущена (чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ================ ЗАКРЫТИЕ ОКОН (ЛЮБЫХ) ======================
!sc02D:: ; ALT+X - закрытие любых окон
;-----------------------------------------------------------------------------
WinGetClass, Win_Class, A ; получить класс активного окна
WinGetActiveTitle, Win_To_Close_Title ; получить заголовок активного окна
If ( Win_Class = "Shell_TrayWnd" OR Win_Class = "ProgMan" OR Win_Class = "AltDesk1.x" ) ; если окно - "панель задач" или "рабочий стол" или AltDesk, то...
Return ; закончить обработку горячей клавиши (не выходить из Windows, или из AltDesk)
; если окно не из вышеперечисленных, то...
If Win_Class = BaseWindow_RootWnd ; если окно - Winamp...
{
WinClose, ahk_class Winamp v1.x ; закрыть Winamp
Return ; закончить обработку горячей клавиши
}
If Win_Class = PROCEXPL ; если окно - Process Explorer...
{
;~ WinMenuSelectItem, ahk_class PROCEXPL,, File, Exit ; можно использовать эту строку, а можно ту, что ниже (она универсальнее)
PostMessage, 0x111, 40001,,, ahk_class PROCEXPL ; выбрать пункт меню File -> Exit
Return ; закончить обработку горячей клавиши
}
IfWinActive, HDDlife Pro - ; если активно окно HDDlife Pro...
{
WinMenuSelectItem,,, 1&, 5& ; выбрать меню Файл -> Выход
Return ; закончить обработку горячей клавиши
}
; если окно - не из вышеперечисленных, то...
; закрыть окно по заголовку, т.к. WinClose, WinKill, PostMessage - не закрывает неспецифицированные ahk_class #32770
; указать через запятую фрагменты заголовков окон, которые нужно закрыть (пробелов после запятой не делать)
If Win_To_Close_Title contains AWicons,FreeMemory ; список фрагментов заголовков окон
Send !{F4} ; закрыть окно по заголовку
Else ; если окно должно закрываться не по заголовку, то...
WinClose, ahk_class %Win_Class% ; закрыть окно по классу
KeyWait, sc02D ; ожидать пока клавиша "X" не будет отпущена (чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ========== ЗАКРЫТИЕ ОКОН БЕЗ СОХРАНЕНИЯ ==================
!#sc02D:: ; ALT+WIN+X - закрытие окон без сохранения
;-----------------------------------------------------------------------------
WinGetClass, Win_Class, A ; получить класс активного окна
If ( Win_Class = "Shell_TrayWnd" OR Win_Class = "ProgMan" OR Win_Class = "AltDesk1.x" ) ; если окно - "панель задач" или "рабочий стол" или AltDesk, то...
Return ; закончить обработку горячей клавиши (не выходить из Windows)
; если окно - не из вышеперечисленных, то...
WinClose, ahk_class %Win_Class% ; закрыть окно
Sleep, 200 ; пауза для ожидания окна с вопросом о сохранении
Send {TAB} ; перейти на кнопку "нет"
Sleep, 50 ; пауза для реакции перехода на нужную кнопку
Send {ENTER} ; и нажать её
KeyWait, sc02D ; ожидать пока клавиша "X" не будет отпущена (чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ========== СВЕРНУТЬ - РАЗВЕРНУТЬ ОКНО ==================
#sc01F:: ; WIN+S - свернуть окно (ДВОЙНОЕ нажатие - развернуть)
;-----------------------------------------------------------------------------
If Count_Presses > 0 ; если таймер уже запущен, то...
{
Count_Presses += 1 ; плюсуем каждое нажатие клавиши (число будет обрабатываться в подпрограмме соответствующего таймера)
Return ; закончить обработку горячей клавиши (ее дальнейшую обработку уже определяет таймер и его подпрограмма)
}
; иначе - это первое нажатие из новой серии
Count_Presses = 1 ; выставляем флаг, что клавиша один раз нажата
SetTimer, Timer_Presses_1, 300 ; переходить к указанной подпрограмме через каждые 300 миллисекунд
Return ; закончить обработку горячей клавиши
Timer_Presses_1: ; подпрограмма действий в зависимости от количества нажатий
SetTimer, Timer_Presses_1, off ; выключить таймер
If Count_Presses = 1 ; если клавиша нажата однажды...
{
WinGet, Win_ID, ID, A ; сохранить ID сворачиваемого окна в переменной
WinGetClass, Win_Class, A ; получить класс активного окна
If Win_Class = BaseWindow_RootWnd ; если класс окна - Winamp
{
Count_Presses = 0 ; сбросить счет и подготовится к следующему ряду нажатий
Goto, WinAmp_Min_Restore ; ==> перейти к метке свернуть WinAmp (WinAmp_Min_Restore)
; Целиком скрипт для управления WinAmp'ом можно найти здесь
; http://forum.script-coding.com/viewtopic.php?id=75
; Но чтобы этот (текущий) скрипт не "ошибался", я поместил сюда небольшой фрагментик упомянутого скрипта
; См. самую последнюю подпрограмму
}
; если окно - не winamp, то...
WinMinimize, ahk_class %Win_Class% ; свернуть окно
}
If Count_Presses = 2 ; если клавиша нажата дважды...
{
If Win_Class = BaseWindow_RootWnd ; если класс окна - Winamp
{
Count_Presses = 0 ; сбросить счет и подготовится к следующему ряду нажатий
Goto, WinAmp_Min_Restore ; ==> перейти к метке Развернуть WinAmp (WinAmp_Min_Restore)
}
; если окно не winamp, то...
WinRestore, ahk_id %Win_ID% ; восстановить свернутое окно с запомненным ID
WinActivate, ahk_id %Win_ID% ; активизировать его
; Не все окна нормально реагируют на команду PostMessage, 0x112, 0xF120,,, ahk_id %Win_ID%
; 0x112 = WM_SYSCOMMAND, 0xF120 = SC_RESTORE - развернуть
; 0x112 = WM_SYSCOMMAND, 0xF020 = SC_MINIMIZE - минимизировать
}
Count_Presses = 0 ; сбросить счет и подготовится к следующему ряду нажатий
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ========== МАКСИМИЗИРОВАТЬ - ВОССТАНОВИТЬ ОКНО ==================
#sc010:: ; WIN+Q - максимизировать/восстановить окно
;-----------------------------------------------------------------------------
WinGetClass, Win_Class, A ; получить класс активного окна
; НЕ ОБРАБАТЫВАТЬ ОКНО WINAMP
If Win_Class = BaseWindow_RootWnd ; если класс окна - Winamp
Return ; закончить обработку горячей клавиши
; если окно - не winamp, то...
WinGetPos, X, Y,,, A ; получить позицию текущего окна
If ( X=-4 and Y=-4) ; если окно максимизировано, то...
WinRestore, A ; восстановить окно
Else ; если не максимизировано, то...
WinMaximize, A ; максимизировать окно
KeyWait, sc010 ; ожидать пока клавиша "Q" не будет отпущена (чтобы исключить срабатывание от простого удержания нажатой клавиши)
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ========== НАЗНАЧИТЬ/СНЯТЬ ОКНО - ПОВЕРХ ВСЕХ ==================
#sc01E:: ; WIN+A (английская) - окно "поверх всех" (ДВОЙНОЕ нажатие - снять "поверх всех")
;-----------------------------------------------------------------------------
If Count_Presses > 0 ; если таймер уже запущен, то...
{
Count_Presses += 1 ; плюсуем каждое нажатие клавиши (число будет обрабатываться в подпрограмме соответствующего таймера)
Return ; закончить обработку горячей клавиши (ее дальнейшую обработку уже определяет таймер и его подпрограмма)
}
; Иначе - это первое нажатие из новой серии
Count_Presses = 1 ; выставляем флаг, что клавиша один раз нажата
SetTimer, Timer_Presses_2, 300 ; переходить к указанной подпрограмме через каждые 300 миллисекунд
Return ; закончить обработку горячей клавиши
Timer_Presses_2: ; подпрограмма действий в зависимости от количества нажатий
SetTimer, Timer_Presses_2, off ; выключить таймер
If Count_Presses = 1 ; если клавиша нажата однажды...
{
; ОБРАБОТАТЬ ОКНО WINAMP
WinGetClass, Win_Class, A ; получить класс активного окна
If Win_Class = BaseWindow_RootWnd ; если класс окна - Winamp
{
PostMessage, 0x111, 40019,,, ahk_class Winamp v1.x ; окно - поверх всех
Goto, LabelEXIT2 ; ==> перейти к окончанию обработки
} ; если окно не Winamp, то...
WinGet, Win_ID, ID, A ; получить ID активного окна
WinSet, AlwaysOnTop, ON, ahk_id %Win_ID% ; окно - поверх всех
}
Else If Count_Presses = 2 ; если клавиша нажата дважды...
{
; ОБРАБОТАТЬ ОКНО WINAMP
WinGetClass, Win_Class, A ; получить класс активного окна
If Win_Class = BaseWindow_RootWnd ; если класс окна - Winamp
PostMessage, 0x111, 40019,,, ahk_class Winamp v1.x ; снять "поверх всех"
WinGet, Win_ID, ID, A ; получить ID активного окна
WinSet, AlwaysOnTop, OFF, ahk_id %Win_ID% ; снять "поверх всех"
}
LabelEXIT2:
Count_Presses = 0 ; сбросить счет и подготовится к следующему ряду нажатий
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------
; ========== ПЕРЕМЕЩЕНИЕ ОКНА МЫШЬЮ (EWD) ==================
; Это - чуть-чуть переделанных скрипт из справки к AutoHotkey - Easy Window Dragging (EWD)
#LButton:: ; WIN+Левая мышь - перемещение окон за любое место внутри окна
;-----------------------------------------------------------------------------
; Вы можете отпустить клавишу WIN после нажатия левой кнопки, вместо того, чтобы удерживать ее
; И вы можете во время перемещения нажать Escape, чтобы отменить перемещение
CoordMode, Mouse ; переключиться на абсолютные координаты экрана
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin ; получить начальную позицию мыши и ID окна под мышью
WinGetClass, EWD_Win_Class, ahk_id %EWD_MouseWin% ; получаем класс окна под мышью
If EWD_Win_Class = ProgMan ; если это рабочий стол, то...
Return ; закончить обработку горячей клавиши
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin% ; запоминаем исходные координаты окна
SetTimer, EWD_WatchMouse, 10 ; переходить к указанной подпрограмме через каждые 10 мс
Return ; закончить обработку горячей клавиши
EWD_WatchMouse: ; подпрограмма обработки событий в таймере
EWD_Work = 1 ; флаг, что подпрограмма выполняется (он нужен для корректной работы закрытия окон по Escape)
GetKeyState, EWD_LButtonState, LButton, P ; проверить нажата ли левая кнопка мыши
If EWD_LButtonState = U ; если кнопка отпущена, то закончить перемещение окна...
{
SetTimer, EWD_WatchMouse, off ; отключить таймер
EWD_Work = ; сбрасываем флаг, что подпрограмма выполняется
Return ; конец подпрограммы, закончить обработку горячей клавиши
}
GetKeyState, EWD_EscapeState, Escape, P ; проверить нажата ли клавиша Escape
If EWD_EscapeState = D ; если нажата, то отменить перемещение окна (вернуть его в начальные координаты)
{
SetTimer, EWD_WatchMouse, off ; отключить таймер
EWD_Work = ; сбрасываем флаг, что подпрограмма выполняется
WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY% ; вернуть окно в начальные координаты
Return ; конец подпрограммы, закончить обработку горячей клавиши
}
; ...если кнопка нажата, то перемешать окно вслед за перемещением указателя мыши
CoordMode, Mouse ; переключиться на абсолютные координаты экрана
MouseGetPos, EWD_MouseX, EWD_MouseY ; получить текущие координаты мыши
WinGetPos, EWD_WinX, EWD_WinY,,, ahk_id %EWD_MouseWin% ; получить позицию окна под мышкой
SetWinDelay, -1 ; перемещать окно немедленно
; переместить окно под мышью вслед за мышью
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY
EWD_MouseStartX := EWD_MouseX ; обновить X координату для следующего вызова этой подпрограммы по таймеру
EWD_MouseStartY := EWD_MouseY ; обновить Y координату для следующего вызова этой подпрограммы по таймеру
Return ; закончить подпрограмму и обработку горячей клавиши
;-----------------------------------------------------------------------------
WinAmp_Min_Restore: ; метка входа из WIN + S (фрагмент скрипта для управления Winamp'ом)
;-----------------------------------------------------------------------------
WinGet, State, MinMax, ahk_class Winamp v1.x
If State = -1 ; если окно минимизировано, то...
WinActivate, ahk_class Winamp v1.x ; восстановить свернутое окно
else ; если окно НЕ минимизировано, то...
{
IfWinActive, ahk_class BaseWindow_RootWnd ; если окно активно, то...
WinMinimize, ahk_class Winamp v1.x ; свернуть окно
else ; если окно НЕ активно, то...
WinActivate, ahk_class Winamp v1.x ; активизировать окно (вывести на передний план)
}
Return ; закончить обработку горячей клавиши
;-----------------------------------------------------------------------------