1

Тема: AHK: Номер окна в Z-последовательности

Как известно, при нажатии Alt-Tab, окна в меню выстраиваются в порядке их использования. Как бы узнать, скажем хендл второго окна в этом списке?
WinAPI?
Хочется сделать чисто программный аналог Alt-Tab м/у 2 окнами.

2

Re: AHK: Номер окна в Z-последовательности

Можно как нибудь отметить окна (запомнить их идентификаторы), затем уже переключаться между ними командой WinActivate.

3 (изменено: stealzy, 2014-09-13 16:59:55)

Re: AHK: Номер окна в Z-последовательности

Думал об этом, но некрасиво как-то.
Пытался так:

wCmd := "GW_HWNDNEXT"
WinGet, hWnd, ID, A

NextWinHwnd := DllCall("GetNextWindow", "Uint", hWnd, "Uint", wCmd)
MsgBox % NextWinHwnd
WinActivate, AHK_id %NextWinHwnd%

Но хендл получить не удается

4

Re: AHK: Номер окна в Z-последовательности

Возможно, это поможет?
Правда, что за хендл получается, выяснить не удалось - переключение было один раз, видимо случайно.

hWnd := WinExist("A")
NextWinHwnd := DllCall("GetWindow", "Ptr", hWnd, "Uint", 2)
MsgBox % NextWinHwnd
WinActivate, ahk_id %NextWinHwnd%
Return

5 (изменено: Irbis, 2014-09-14 11:06:41)

Re: AHK: Номер окна в Z-последовательности

Таким образом переключается между двумя последними окнами:

#WinActivateForce
F12::
   hWnd := WinExist("A")
   Loop {
      Hwnd := DllCall("GetWindow", "Ptr", hWnd, "Uint", 2)
      WinGetTitle, Title, ahk_id %Hwnd%
   } Until Title
   WinActivate, ahk_id %Hwnd%
Return

6 (изменено: stealzy, 2014-09-14 15:25:33)

Re: AHK: Номер окна в Z-последовательности

Спасибо, повесил на NumLock.
Но мне не понятно, как Вы до этого додумались?
Вот я читаю про ф-ю GetWindow:

+ GetWindow

Функция GetWindow отыскивает дескриптор окна, который имеет определенное отношение (Z - последовательность или владелец) к заданному окну.

Синтаксис
HWND GetWindow
(
HWND hWnd, // дескриптор первоначального окна
UINT uCmd // флажок отношения
);

Параметры

hWnd
Идентифицирует окно. Отыскивает дескриптор окна, относящийся к этому окну, основанному на значении параметра uCmd.

uCmd
Определяет отношение между определяемым окном и окном, чей дескриптор должен быть найден. Этот параметр может быть одним из следующих значений:
GW_CHILD - Найденный дескриптор идентифицирует дочернее окно наверху Z - последовательности, если определяемое окно - родительское окно; иначе, найденный дескриптор значение ПУСТО (NULL).Функция проверяет только дочерние окна заданного окна. Она не проверяет окна - потомки.
GW_HWNDFIRST - Найденный дескриптор идентифицирует окно того же самого типа, которое является самым высоким в Z - последовательности. Если определяемое окно - самое верхнее окно, дескриптор идентифицирует самое верхнее окно, которое является самым высоким в Z - последовательности. Если определяемое окно - окно верхнего уровня, дескриптор идентифицирует окно верхнего уровня, которое является самым высоким в Z - последовательности. Если определенное окно - дочернее окно, дескриптор идентифицирует сестринское окно, которое является самым высоким в Z - последовательности.
GW_HWNDLAST - Найденный дескриптор идентифицирует окно того же самого типа, который является самым низким в Z - последовательности. Если определяемое окно - самое верхнее окно, дескриптор идентифицирует самое верхнее окно, которое является самым низким в Z - последовательности. Если определяемое окно - окно верхнего уровня, дескриптор идентифицирует окно верхнего уровня, которое является самым низким в Z - последовательности. Если определяемое окно - дочернее окно, дескриптор идентифицирует сестринское окно, которое является самым низким в Z - последовательности.
GW_HWNDNEXT - Найденный дескриптор идентифицирует окно ниже определяемого окна в Z - последовательности. Если определяемое окно - самое верхнее окно, дескриптор идентифицирует самое верхнее окно ниже определяемого окна. Если определяемое окно - окно верхнего уровня, дескриптор идентифицирует окно верхнего уровня ниже определяемого окна. Если определяемое окно - дочернее окно, дескриптор идентифицирует сестринское окно ниже определяемого окна.
GW_HWNDNEXT - Найденный дескриптор идентифицирует окно ниже определяемого окна в Z - последовательности. Если определяемое окно - самое верхнее окно, дескриптор идентифицирует самое верхнее окно ниже определяемого окна. Если определяемое окно - окно верхнего уровня, дескриптор идентифицирует окно верхнего уровня ниже определяемого окна. Если определяемое окно - дочернее окно, дескриптор идентифицирует сестринское окно ниже определяемого окна.
GW_OWNER - Найденный дескриптор идентифицирует окно владельца определяемого окна, если таковой имеется.

Почему второй параметр — число 2, а не строка GW_HWNDNEXT?
Почему пишется Ptr, а не Uint? И какая разница, если на работу кода это не влияет? Видимо, это просто запись "для себя", типа комментария?
Почему используется одна переменная hwnd и для исходного, и для следующего окна? Я попробовал их разделить, но тогда код просто не работает!

#WinActivateForce
vk90::
   hWnd := WinExist("A")
   Loop {
      NEXThWnd:= DllCall("GetWindow", "Uint", hWnd, "Ptr", 2)
      WinGetTitle, Title, ahk_id %NEXThWnd%
   } Until Title
   WinActivate, ahk_id %NEXThWnd%
Return

7 (изменено: Irbis, 2014-09-14 15:59:53)

Re: AHK: Номер окна в Z-последовательности

Все верно, только нужно учесть, что GW_CHILD и т.д. - это константы, определенные в заголовочном файле (winuser.h) при компиляции программ C/C++. Фактически в GetWindow передаются числа, а про константы AHK "не знает".
Можно прописать в коде:

GW_HWNDNEXT = 2

и вызывать получение дескриптора такой командой

Hwnd := DllCall("GetWindow", "Ptr", hWnd, "Uint", GW_HWNDNEXT)

8 (изменено: stealzy, 2014-09-14 15:24:53)

Re: AHK: Номер окна в Z-последовательности

Благодарю, неочевидно!
Но отчего не работает код с разделением переменных исходного и искомого окна, который я привел выше?

9 (изменено: Irbis, 2014-09-14 21:12:50)

Re: AHK: Номер окна в Z-последовательности

Сначала ты получаешь дескриптор активного окна

hWnd := WinExist("A")

а затем в цикле получаешь предыдущее по отношению к нему

NEXThWnd:= DllCall("GetWindow", "Ptr", hWnd, "Uint", 2)

То есть каждый раз один и тот же дескриптор. В моем примере hWnd меняется в цикле до тех пор, пока он не станет дескриптором окна, имеющего заголовок (Title).

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

#WinActivateForce
vk90::
   NEXThWnd := hWnd := WinExist("A")
   Loop {
      NEXThWnd:= DllCall("GetWindow", "Ptr", NEXThWnd, "Uint", 2)
      WinGetTitle, Title, ahk_id %NEXThWnd%
   } Until Title
   WinActivate, ahk_id %NEXThWnd%
Return

; Активировать окно, бывшее в фокусе при последнем нажатии NumLock
F12::
   WinActivate, ahk_id %hWnd%
Return

10

Re: AHK: Номер окна в Z-последовательности

А, значит в Z-последовательности находятся все окна в системе, а не только видимые верхнего уровня. А цикл перебирает окна.
Наивно думал, что цикл применен "для надежности" срабатывания.

11

Re: AHK: Номер окна в Z-последовательности

stealzy пишет:

<...> Почему пишется Ptr, а не Uint? И какая разница, если на работу кода это не влияет? Видимо, это просто запись "для себя", типа комментария? <...>

Размер данных совпадает, и в данном случае AHK позволяет "вольности", не проверяя тип используемых данных, но судя по описанию функции, первый параметр рассматривается именно как указатель, а второй - как целое число без знака. Не хочется иметь в таком коротком коде "глюк" при запуске скрипта в системах с разной битностью или при переходе с AHK 32бит на 64-битную версию.