Тема: AHK: Универсальная функция получения информации об окнах
Из-за разнообразия названий команд получения информации об окнах, забываю как именно пишутся нек. команды ( то ли [Win%X%, Var, Title], то ли [WinGet, Var, %X%, Title], или IfWin%X% ).
Плюс раздражала смена опций DetectHiddenWindows, SetTitleMatchMode, когда меняешь их ради одной команды, а потом меняешь обратно. Если меняешь их в функции, то надо еще и сохранять старые значения и восстанавливать их потом.![]()
Задумка: одна универсальная функция для получения информации об окнах, опции DHW и STMM в параметрах. (на выходе восстанавливаются)
WinGetI(Cmd[, ahk_x_name, DetectHiddenWindows, SetTitleMatchMode, WinText, ExcludeTitle, ExcludeText])
Exist, Active, Title, Class, Text, Pos, ID, IDLast, PID, ProcessName, Count, List, MinMax, Style, ExStyle, Transparent, TransColor, ControlList, ControlListHwnd; OwnerID, ClientPos, CommandLine
;Все возможные параметры: Exist, Active, Title, Class, Text, Pos, ID, IDLast, PID, ProcessName, Count, List, MinMax, Style, ExStyle, Transparent, TransColor, ControlList, ControlListHwnd; OwnerID - возвращает Id окна-владельца, ClientPos - координаты клиентской области окна в нумерованном массиве, CommandLine - путь и параметры процесса.
;Если окно не существует, возвращает "".
;Примеры:
;windowID := WinGetI("Id, XTitle AHK_class TMainForm, on")
;windowID := WinGetI("ID", "XTitle AHK_class TMainForm", "On")
;procPID := WinGetI("pid, AHK_id " . windowID . ", On")
;XWinPos := WinGetI("pos, XTitle")
;MsgBox %XWinPos[1]% %XWinPos[2]% %XWinPos[3]% %XWinPos[4]%
WinGetI(Cmd, ahk_x_name="", DetectHiddenWindows="", SetTitleMatchMode="", WinText="", ExcludeTitle="", ExcludeText="") {
if InStr(Cmd, ",") { ; парсим 1 параметр, если он содержит запятые
ParamArray := StrSplit(Cmd, ",", " `t")
Cmd := ParamArray[1]
ahk_x_name := ParamArray[2]
DetectHiddenWindows := ParamArray[3]
SetTitleMatchMode := ParamArray[4]
WinText := ParamArray[5]
ExcludeTitle := ParamArray[6]
ExcludeText := ParamArray[7]
}
if (DetectHiddenWindows!="On" && DetectHiddenWindows!="Off" && DetectHiddenWindows!="")
Return BadParam("DetectHiddenWindows", DetectHiddenWindows)
if (SetTitleMatchMode!="1" && SetTitleMatchMode!="2" && SetTitleMatchMode!="3" && SetTitleMatchMode!="RegEx" && SetTitleMatchMode!="")
Return BadParam("SetTitleMatchMode", SetTitleMatchMode)
Old_DetectHiddenWindows:=A_DetectHiddenWindows
Old_SetTitleMatchMode:=A_TitleMatchMode
if DetectHiddenWindows
DetectHiddenWindows, %DetectHiddenWindows%
if SetTitleMatchMode
SetTitleMatchMode, %SetTitleMatchMode%
Value:=WinGetIRefined(Cmd, ahk_x_name, WinText, ExcludeTitle, ExcludeText)
if DetectHiddenWindows
DetectHiddenWindows, %Old_DetectHiddenWindows%
if SetTitleMatchMode
SetTitleMatchMode, %Old_SetTitleMatchMode%
Return Value
}
WinGetIRefined(Cmd, ahk_x_name, WinText="", ExcludeTitle="", ExcludeText="") {
Static WinGetParamList:={} ; параметры ф-ии WinGet()
WinGetParamList:=[ "ID", "IDLast", "PID", "ProcessName"
, "Count", "List", "MinMax", "Style", "ExStyle", "Transparent", "TransColor"
, "ControlList", "ControlListHwnd", "ProcessPath"]
for k, v in WinGetParamList
if (Cmd=WinGetParamList[k]) {
WinGet, Value, %Cmd%, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
if (Cmd="List") {
i:=0
Loop %Value% {
if ! i++ ; в первом цикле Value из переменной становиться массивом
Value:={}
Value[A_Index] := (Value%A_Index%)
}
}
Return Value
}
if (Cmd="Exist")
Value:=WinExist(ahk_x_name, WinText, ExcludeTitle, ExcludeText)
else if (Cmd="Active")
Value:=WinActive(ahk_x_name, WinText, ExcludeTitle, ExcludeText)
else if (Cmd="Title")
WinGetTitle, Value, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
else if (Cmd="Class")
WinGetClass, Value, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
else if (Cmd="Text")
WinGetText, Value, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
else if (Cmd="Pos") {
WinGetPos, X, Y, Width, Height, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
Value:={}
Value:=[X, Y, Width, Height]
} else if InStr(Cmd, "Own") {
WinID := WinExist(ahk_x_name, WinText, ExcludeTitle, ExcludeText)
Value := DllCall("GetWindow", Ptr, WinID, UInt, GW_OWNER := 4, Ptr)
} else if (Cmd="CommandLine") {
WinGet, pid, pid, %ahk_x_name%, %WinText%, %ExcludeTitle%, %ExcludeText%
ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process WHERE ProcessId = " . pid)._NewEnum.next(x)
Value := x.CommandLine
} else if InStr(Cmd, "Client") {
if !Hwnd:=WinExist(ahk_x_name)
Return
VarSetCapacity(pt, 16)
NumPut(x, pt, 0)
NumPut(y, pt, 4)
NumPut(w, pt, 8)
NumPut(h, pt, 12)
if (!DllCall("GetClientRect", "uint", hwnd, "uint", &pt))
Return
if (!DllCall("ClientToScreen", "uint", hwnd, "uint", &pt))
Return
x := NumGet(pt, 0, "int")
y := NumGet(pt, 4, "int")
w := NumGet(pt, 8, "int")
h := NumGet(pt, 12, "int")
Value:={}
Value:=[x, y, w, h]
} else
Return BadParam("Cmd", Cmd)
Return Value
}
BadParam(name, Cmd) {
MsgBox,16, WinGetI, Parameter %name%="%Cmd%" is not support
Return
}+Можно забыть про зоопарк из 9 команд: IfWinActive, IfWinExist, WinGet, WinGetClass, WinGetPos, WinGetTitle, WinGetText, WinGetActiveStats, WinGetActiveTitle.
+OwnerID - возвращает Id окна-владельца,
+ClientPos - координаты клиентской области окна.
ClientCoord:=WinGetI("clientpos") ; x:=ClientCoord[1], width:=ClientCoord[3]
+CommandLine - путь и параметры с которыми запущен процесс окна
"C:\Windows\calc.exe"
/solve_ferma_theorem
+Валидация параметров.
Применение фунции с параметром Pos возвращает нумер. массив, ассоциативный, возможно будет понятнее (winPos["y"] vs winPos[2]), но лень писать кавычки;
Параметры Exist и ID эквиваленты;
Нестрогий синтаксис ahk_x abcd. Теоретически, название окна может содержать ahk_x либо запятые.
Посмотрел, как это сделано в AutoIt - эти параметры передаются в ф-ию асс. массивом:
f(..., Title: abcd, ...) если несколько условий, то: f(..., [Title: abcd, Class: xyzw] ...)
----------------------------
fixed: с параметром List возвращает в переменную массив контролов.

