1

Тема: AHK: скрытие и отображение активного окна по горячим клавишам

Я пишу по поводу этой темы, которая почему-то имеет статус read only, так что там я задать вопрос не могу.
У меня просьба на доработку этого скрипта: он записывает ID только тех скрываемых окон, которые скрывали через хоткей. А хотелось бы, чтоб записывались любые, т.е. даже если я ни 1 окна не скрыл хоткеем, чтобы я мог восстановить последнее окно, которое я скрыл, например, мышью.
Подправьте чутка скрипт, пожалуйста.

2

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

Я пишу по поводу этой темы, которая почему-то имеет статус read only, так что там я задать вопрос не могу.

Писать в «Коллекцию …» могут только Администраторы. Модераторы и Разработчики: §6. Разделы форума и права посетителей. Тем не менее, там же сказано:

Обсуждения и дискуссии в данном разделе не допускаются. Для этого существует форум "Разработка скриптов" в разделе "Общение". Если необходимо обсудить выложенную разработку или задать вопрос, создайте тему на форуме "Разработка скриптов" со ссылкой на соответствующую тему этого раздела.

Так что, просто создавайте тему в «Разработке …», где укажите ссылку на соответствующую тему, например: Серый форум / AutoHotkey: скрытие и отображение активного окна по горячим клавишам.

3

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

Подправьте чутка скрипт, пожалуйста.

Обращаю внимание специалистов (дабы не затерялось на фоне моего предыдущего поста).

4

Re: AHK: скрытие и отображение активного окна по горячим клавишам

alexii пишет:

Писать в «Коллекцию …» могут только Администраторы. Модераторы и Разработчики: §6. Разделы форума и права посетителей. Тем не менее, там же сказано:

Обсуждения и дискуссии в данном разделе не допускаются. Для этого существует форум "Разработка скриптов" в разделе "Общение". Если необходимо обсудить выложенную разработку или задать вопрос, создайте тему на форуме "Разработка скриптов" со ссылкой на соответствующую тему этого раздела.

Это то я знаю, просто это не логично вообще.

alexii пишет:

Так что, просто создавайте тему в «Разработке …», где укажите ссылку на соответствующую тему, например: Серый форум / AutoHotkey: скрытие и отображение активного окна по горячим клавишам.

Где найти эту "Разработку ..."? Здесь разве не тот раздел, в который следовало обращаться?

5

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

Где найти эту "Разработку ..."? Здесь разве не тот раздел, в который следовало обращаться?

Drugoy, всё правильно, ты обратился, куда нужно было.

По теме.

Drugoy пишет:

чтобы я мог восстановить последнее окно, которое я скрыл, например, мышью.

В скрипте идёт речь о скрытии/показе окна, мышью же можно либо минимизировать, либо вовсе закрыть окно, а как раз скрыть нельзя (если это специально не предусмотрено в приложении). Ты какое действие имел в виду?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

Где найти эту "Разработку ..."? Здесь разве не тот раздел, в который следовало обращаться?

Именно этот самый, где и находится эта тема. В оригинале это был один раздел, называвшийся «Разработка скриптов». Потом его «раздраконили» на подразделы по тематике. Так что — тут всё правильно. Я, скорее, имел в виду, что просто report'ить смысла нет, надо именно создавать новую (или поднимать существующую) тему в «Разработке …».

Drugoy пишет:

…просто это не логично вообще.

Про более логичные варианты — милости прошу в эту: OFF: организационные вопросы тему. Всё обсуждаемо.

7

Re: AHK: скрытие и отображение активного окна по горячим клавишам

teadrinker пишет:
Drugoy пишет:

чтобы я мог восстановить последнее окно, которое я скрыл, например, мышью.

В скрипте идёт речь о скрытии/показе окна, мышью же можно либо минимизировать, либо вовсе закрыть окно, а как раз скрыть нельзя (если это специально не предусмотрено в приложении). Ты какое действие имел в виду?

Спасибо, что указали мне на мою невнимательность. Я-то подумал, что под скрытием имеется в виду процесс сворачивания окна.
Тогда, просьбу немного подкорректирую - можно ли аналогичный скрипт, который вместо скрытия окна - его сворачивает. Ну и изначальной требование то же: чтобы запоминались и те окна, которые я сворачивал мышью.

8

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Если ты свернул окно горячей клавишей, а потом другое окно мышью, то что должно происходить при повторном нажатии горячей клавиши? Разворачиваться первое окно? Второе? В каком случае окна по горячей клавише должны сворачиваться, если существуют уже несколько свёрнутых ранее мышью? В общем, нужно алгоритм работы поподробнее.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9 (изменено: Grey, 2011-12-30 05:18:14)

Re: AHK: скрытие и отображение активного окна по горячим клавишам

SetBatchLines, -1
DllCall("RegisterShellHookWindow", "UInt", A_ScriptHwnd)
MsgNum:=DllCall("RegisterWindowMessage", "Str","SHELLHOOK")
OnMessage(MsgNum, "ShellMessage")
OnExit, ExitScript
Return

!vkC0:: ; alt+tilde
   If hwndback
   {
      WinRestore, % "ahk_id"hwndback
      WinActivate, % "ahk_id"hwndback
      hwndback:=
   }
   Else
      WinMinimize, A
   KeyWait, vkC0
   Return

ShellMessage(wParam, lParam)
{
   global
   If wParam=5
   {
      hwnd:=NumGet(lParam+0)
      If DllCall("IsIconic", "Ptr", hwnd)
         hwndback:=hwnd
   }
}

ExitScript:
   DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd)
   ExitApp

10

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Grey, не стоило так торопиться, лучше было бы сначала выслушать коллегу Drugoy. По твоему коду, если свернуть окно горячей клавишей, потом развернуть мышью, затем снова нажать горячую клавишу — то ничего не происходит.
Потом, функция RegisterShellHookWindow():

[This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]

Есть альтернативные варианты.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: скрытие и отображение активного окна по горячим клавишам

teadrinker пишет:

Если ты свернул окно горячей клавишей, а потом другое окно мышью, то что должно происходить при повторном нажатии горячей клавиши?

Хороший вопрос.
Очевидно, что на сворачивание текущего окна и на разворачивание последнего свёрнутого окна должны быть выставлены 2 разных хоткея.
Хотелось бы Win+Ctrl на сворачивание и Ctrl+Win на разворачивание.

12

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

Хотелось бы Win+Ctrl на сворачивание и Ctrl+Win на разворачивание.

Так как-нибудь:

global ArrayMinimisedID := []
global EVENT_SYSTEM_MINIMIZESTART := 0x16
global EVENT_SYSTEM_MINIMIZEEND := 0x17

WinGet, List, List
Loop % List
{
   WinGet, MinMax, MinMax, % "ahk_id" List%A_Index%
   if MinMax = -1
      ArrayMinimisedID.Insert(List%A_Index%)
}

DllCall("SetWinEventHook", UInt, EVENT_SYSTEM_MINIMIZESTART
                         , UInt, EVENT_SYSTEM_MINIMIZEEND
                         , UInt, 0
                         , UInt, RegisterCallback("HookProc", "F")
                         , UInt, 0
                         , UInt, 0
                         , UInt, 0)
Return
                         
HookProc(hWinEventHook, event, hwnd)
{
   if (event = EVENT_SYSTEM_MINIMIZESTART)
      ArrayMinimisedID.Insert(1, hwnd)

   if (event = EVENT_SYSTEM_MINIMIZEEND)
      for k, v in ArrayMinimisedID
         if (v = hwnd)
            ArrayMinimisedID.Remove(k, k)
}

~*LCtrl::
   if !GetKeyState("LWin", "P")
      Return
      
   WinGetClass, class, A
   if !(class ~= "Progman|WorkerW|Shell_TrayWnd")
      WinMinimize, A
   Return

*LWin::
   if !GetKeyState("LCtrl", "P")
      Return
      
   ID := ArrayMinimisedID.1
   WinRestore, % "ahk_id " ID
   WinActivate, % "ahk_id " ID
   Return

Только на левые Win и Ctrl.
Требует AHK_L v1.1.05+

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13 (изменено: Drugoy, 2011-12-30 01:06:49)

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Спасибо, работает, но выбран плохой подход: этот скрипт делает невозможным использование любых системных хоткеев начинающихся с Win, если использовать левую Win. Для меня это не допустимо.
Мне также интересно и самому научиться скриптить на AHK, а потому имеется ряд вопросов и просьб.
1. Пожалуйста, исправьте скрипт таким образом, чтобы избежать конфликта, приводящего к невозможности использования Win+... хоткеев, при нажатии LWin.
2.А. Прикрутите пожалуйста к скрипту массовое действие если используется Shift:
Win+Shift+Ctrl = сделать так, чтобы посылался Win+D (ну или, может быть, лучше будет не ссылаться на системный хоткей, а просто назначить выполнение этой же функции. Ну а повторное нажатие - чтобы их, естественно, возвращало обратно (как это делает и повторное нажатие Win+D).
2.Б. Прозреваю, что возможен конфликт с хоткеем Win+Ctrl, которого хотелось бы избежать.
3. И можно ещё тогда сразу же попросить приделать к скрипту ещё 1 функцию?
У меня уже имеется написанный для неё код, но я не знаю куда его было бы правильно вписать:

#`::Winset, Alwaysontop, , A

4. Почему в начале скрипта нет никаких общих строк типа
SetBatchLines, -1
#SingleInstance force
#NoEnv
SetBatchLines, -1
SendMode Input
и т.д.? Если честно я понимаю предназначение не каждой из них, но они есть во многих скриптах.
5. Почему выбрано ограничение на только левые Win и Ctrl? Если я изменю LWin и LCtrl на Win и Ctrl - это чем-то чревато?
6. По возможности - прокомментируйте код, чтобы можно было использовать его в качестве материала для изучения новичками.

14

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Поправка для 2-ого пункта: лучше посылать не Win+D, а Win+M и Win+Shift+M как обратное действие.
Вспомнил, что после нажатия Win+D часто открытие какой-нибудь папки может не только открыть окно этой папки, но в некоторых случаях и другие окна.

15

Re: AHK: скрытие и отображение активного окна по горячим клавишам

1. Это можно, код в конце.
2. Это проблематично, действительно могут возникнуть нестыковки, лучше использовать другую комбинацию. Нужные команды — WinMinimizeAll и WinMinimizeAllUndo.
3. Можно в самый конец кода.
4. В данном случае они не нужны, читай хелп по ним.
5. При использовании Ctrl, Alt и Shift в качестве хоткеев лучше указывать конкретную клавишу, можешь поэкспериментировать с ними. Горячей клавиши Win не существует.
6. Прокомментировал, но для новичка будет сложновато.

global ArrayMinimisedID := []   ; в этот массив будут записываться все минимизированные окна
global EVENT_SYSTEM_MINIMIZESTART := 0x16
global EVENT_SYSTEM_MINIMIZEEND := 0x17
; создаём изначально отключённую горячую клавишу LWin, которую будем включать при необходимости.
Hotkey, *LWin, Win, Off   

WinGet, List, List
Loop % List
{
   WinGet, MinMax, MinMax, % "ahk_id" List%A_Index%
   if MinMax = -1
      ArrayMinimisedID.Insert(List%A_Index%)  ; записываем в массив все минимизированные до начала работы скрипта окна
}
; устанавливаем хук, отслеживающий события минимизации и восстановления
; информация — http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx
DllCall("SetWinEventHook", UInt, EVENT_SYSTEM_MINIMIZESTART
                         , UInt, EVENT_SYSTEM_MINIMIZEEND
                         , UInt, 0
                         , UInt, RegisterCallback("HookProc", "F")
                         , UInt, 0 , UInt, 0 , UInt, 0)
Return

HookProc(hWinEventHook, event, hwnd)
{
   if (event = EVENT_SYSTEM_MINIMIZESTART)
      ArrayMinimisedID.Insert(1, hwnd)   ; при минимизации какого-л. окна записываем его идентификатор в массив

   if (event = EVENT_SYSTEM_MINIMIZEEND)  ; при восстановлении какого-л. окна исключаем его идентификатор из массива
      for k, v in ArrayMinimisedID
         if (v = hwnd)
            ArrayMinimisedID.Remove(k, k)
}

~*LCtrl::
   if !GetKeyState("LWin", "P")
   {
      Hotkey, *LWin, On
      Return
   }

   WinGetClass, class, A
   if !(class ~= "Progman|WorkerW|Shell_TrayWnd")
      WinMinimize, A
   Return

~*LCtrl Up:: Hotkey, *LWin, Off

Win:
   ID := ArrayMinimisedID.1
   WinRestore, % "ahk_id " ID
   WinActivate, % "ahk_id " ID
   Return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Спасибо большое.
Осталась просьба только по пункту 2.
Вот такой код:

#Ctrl::GoSub, Label1
#+Ctrl::GoSub, Label2

Label1:
WinGetClass, class, A
If (class = WorkerW) {
return
} Else {
WinMinimize, A
}
return

Label2:
   Send, #d
return

работает без коллизий.
Привёл этот код в надежде, что с его помощью вам или кому-то ещё - всё-таки удастся добавить выпрашиваемую мной функцию без глюков.

17 (изменено: Drugoy, 2012-01-01 14:41:45)

Re: AHK: скрытие и отображение активного окна по горячим клавишам

Drugoy пишет:

2.Б. Прозреваю, что возможен конфликт с хоткеем Win+Ctrl, которого хотелось бы избежать.

Я так понимаю, что этого можно избежать проверкой через A_PriorKey?

Добавление:
А, не важно: добавил

if !GetKeyState("LShift", "P")
{
...
}

проверку при выполнении кода LWin+LCtrl, так что он не выполняется, если в этот момент нажат шифт, тем самым избежал конфликта.

18

Re: AHK: скрытие и отображение активного окна по горячим клавишам

teadrinker,
У меня вопрос по вашему коду:
Я его изменил вот так:

global ArrayMinimisedID := []
global EVENT_SYSTEM_MINIMIZESTART := 0x16
global EVENT_SYSTEM_MINIMIZEEND := 0x17

WinGet, List, List
Loop % List
{
    WinGet, MinMax, MinMax, % "ahk_id" List%A_Index%
    if MinMax = -1
        ArrayMinimisedID.Insert(List%A_Index%)
}

DllCall("SetWinEventHook", UInt, EVENT_SYSTEM_MINIMIZESTART
                        , UInt, EVENT_SYSTEM_MINIMIZEEND
                        , UInt, 0
                        , UInt, RegisterCallback("HookProc", "F")
                        , UInt, 0 , UInt, 0 , UInt, 0)
Return
 
HookProc(hWinEventHook, event, hwnd)
{
    if (event = EVENT_SYSTEM_MINIMIZESTART)
        ArrayMinimisedID.Insert(1, hwnd)

    if (event = EVENT_SYSTEM_MINIMIZEEND)
        for k, v in ArrayMinimisedID
            if (v = hwnd)
                ArrayMinimisedID.Remove(k, k)
}

~*#Ctrl::
    WinGetClass, class, A
    if !(class ~= "Progman|WorkerW|Shell_TrayWnd|Button")
        WinMinimize, A
    Return


^LWin::
    ID := ArrayMinimisedID.1
    WinRestore, % "ahk_id " ID
    WinActivate, % "ahk_id " ID
    Return

Чем такой подход хуже вашего?

19

Re: AHK: скрытие и отображение активного окна по горячим клавишам


WinWait, Program Window
Winhide, Program Window
WinWaitClose, Program Window
...

В сценарии используется ожидание закрытия окна как условия. В то же время хотелось бы, чтобы само окно было невидимым. Используя представленный вариант окно появляется на короткий промежуток времени. Можно ли предотвратить появление окна, чтобы оно было невидимым с начала активности?
Допускается вариант, при котором останется невозможным опираться на условие закрытия данного окна, т.к. параллельно с ним может использоваться другое окно, которое закрывается одновременно с ним.