diff options
Diffstat (limited to 'tt.windowselect.ahk')
-rw-r--r-- | tt.windowselect.ahk | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/tt.windowselect.ahk b/tt.windowselect.ahk new file mode 100644 index 0000000..ba9abb5 --- /dev/null +++ b/tt.windowselect.ahk @@ -0,0 +1,202 @@ +;; Select window by number ---------------------------------------------------- + +;; -> body + +#1::FocusButton(1) +#2::FocusButton(2) +#3::FocusButton(3) +#4::FocusButton(4) +#5::FocusButton(5) +#6::FocusButton(6) +#7::FocusButton(7) +#8::FocusButton(8) +#9::FocusButton(9) +#0::FocusButton(10) + +;; -> library + +; https://code.google.com/archive/p/activatebynum/ + +Add_hWndToArray(gi, hWnd) +{ + global + g_bundleSize%gi% := g_bundleSize%gi% + 1 + local wi := g_bundleSize%gi% + g_hWnd%gi%_%wi% := hWnd +} + +AddBundle(gi) +{ + global + g_bundleSize%gi% := 0 +} + +BundleSize(gi) +{ + global + return g_bundleSize%gi% +} + +Get_hWndFromArray(gi, wi) +{ + global + return g_hWnd%gi%_%wi% +} + +SetButtonTopLeftLoc(gi, x, y) +{ + global + g_xs%gi% := x + g_ys%gi% := y +} + +Build_hWndArray(maxBundleCount) +{ + global g_bundleCount + + WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd + hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar) + pProc := DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4) + idxTB := GetTaskSwBar() + SendMessage, 0x418, 0, 0, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_BUTTONCOUNT + buttonCount := ErrorLevel + + g_bundleCount := 0 + + Loop, %buttonCount% + { + SendMessage, 0x417, A_Index-1, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETBUTTON + + VarSetCapacity(btn, 32, 0) + DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &btn, "Uint", 32, "Uint", 0) + + idn := NumGet(btn, 4) + Statyle := NumGet(btn, 8, "Char") + dwData := NumGet(btn, 12) + If Not dwData + dwData := NumGet(btn, 16, "int64") + + DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "int64P", hWnd:=0, "Uint", NumGet(btn,12) ? 4:8, "Uint", 0) + + If Not hWnd ; group button, indicates the start of a group + { + If g_bundleCount >= %maxBundleCount% + Break + + hidden := Statyle & 0x08 ; TBSTATE_HIDDEN + If Not hidden + { + grpCollapsed := true + g_bundleCount := g_bundleCount + 1 + AddBundle(g_bundleCount) + + GetTaskbarButtonTopLeft(idn, x, y) + SetButtonTopLeftLoc(g_bundleCount, x, y) + } + Else + grpCollapsed := false + } + else ; actual window button + { + If grpCollapsed + { + Add_hWndToArray(g_bundleCount, hWnd) + } + Else + { + g_bundleCount := g_bundleCount + 1 + AddBundle(g_bundleCount) + Add_hWndToArray(g_bundleCount, hWnd) + + GetTaskbarButtonTopLeft(idn, x, y) + SetButtonTopLeftLoc(g_bundleCount, x, y) + } + } + } + + DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000) + DllCall("CloseHandle", "Uint", hProc) +} + +FocusButton(n) +{ + global g_bundleCount + + ; these static variables can become inaccurate if windows are created or closed + ; inbetween pressing of hotkeys, but in practice, we can safely ignore the + ; inaccuracy + static prevBundleIndex := 0 + static prevWindowIndex := 0 + + Build_hWndArray(n) + + if (g_bundleCount >= n) + { + bundleSize := BundleSize(n) + + if n = %prevBundleIndex% + windowIndex := Mod(prevWindowIndex, bundleSize) + 1 + else + windowIndex := 1 + + hWnd := Get_hWndFromArray(n, windowIndex) + + If bundleSize > 1 ; cycle through windows in the same bundle + WinActivate, ahk_id %hWnd% + Else ; single-window bundle; toggles between activating (restoring) and minimizing the window + IfWinActive, ahk_id %hWnd% + WinMinimize, ahk_id %hWnd% + Else + WinActivate, ahk_id %hWnd% + + prevBundleIndex := n + prevWindowIndex := windowIndex + } +} + +GetTaskSwBar() +{ + ControlGet, hParent, hWnd,, MSTaskSwWClass1 , ahk_class Shell_TrayWnd + ControlGet, hChild , hWnd,, ToolbarWindow321, ahk_id %hParent% + Loop + { + ControlGet, hWnd, hWnd,, ToolbarWindow32%A_Index%, ahk_class Shell_TrayWnd + If Not hWnd + Break + Else If hWnd = %hChild% + { + idxTB := A_Index + Break + } + } + Return idxTB +} + +GetTaskbarButtonTopLeft(id, ByRef x, ByRef y) +{ + idxTB := GetTaskSwBar() + WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd + hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar) + pProc := DllCall("VirtualAllocEx", "Uint", hProc, "Uint", 0, "Uint", 32, "Uint", 0x1000, "Uint", 0x4) + idxTB := GetTaskSwBar() + + SendMessage, 0x433, id, pProc, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd ; TB_GETRECT + ;IfEqual, ErrorLevel, 0, return "Err: can't get rect" + + VarSetCapacity(rect, 32, 0) + DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pProc, "Uint", &rect, "Uint", 32, "Uint", 0) + + DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pProc, "Uint", 0, "Uint", 0x8000) + DllCall("CloseHandle", "Uint", hProc) + + ControlGet, hWnd, hWnd,, ToolbarWindow32%idxTB%, ahk_class Shell_TrayWnd + WinGetPos, x, y, w, h, ahk_id %hWnd% + + left := NumGet(rect, 0) + top := NumGet(rect, 4) + right := NumGet(rect, 8) + bottom := NumGet(rect, 12) + + x := x + left + y := y + top +} |