Jump to content


Photo

Tab windows one at a time forwards and backwards


  • Please log in to reply
5 replies to this topic

#1 berban

berban
  • Members
  • 180 posts

Posted 26 March 2011 - 06:05 AM

This simple-ish script will switch between your windows in Alt+Tab order, one at a time.

PrintScreen will go “forwards”: It will activate the next-highest window (the window you would see if you pressed Alt+Tab once). The current window is minimized. The new window is indicated with a green flash around the border. If there is only one window, the desktop is shown.

ScrollLock will go “backwards”: It activates the bottommost window and flashes it blue. The current window is not minimized. If there is only one window, it is restored if minimized.

Note that PrintScreen puts the top on the bottom, and ScrollLock puts the bottom on the top, so they reciprocate.

PrintScreen & ScrollLock goes to the desktop (the desktop is not part of the normal cycle like it is with Alt+Tab).

CapsLock & PrintScreen and CapsLock & ScrollLock send regular PrintScreen and ScrollLock, respectively.


Note - Dialog boxes (class “#32770”) are not included in the window switching due to odd behavior with child windows in certain cases – for instance, in MSPaint, if the color switcher dialog box is open it counts as a window (for WinGet, , List) when paint is restored but doesn’t when it’s minimized. This screws things up.


Enjoy!

#NoEnv
SetBatchLines, -1
SetWinDelay, 0

CapsLock & PrintScreen::Send {PrintScreen}

CapsLock & ScrollLock::Send {ScrollLock}

$PrintScreen::
Gosub TAB_CheckWindows
If (TAB_List < 2) {
	If Not WinActive("ahk_class WorkerW")
		Send #d
	SoundPlay %A_Windir%\Media\Windows Ding.wav
	TAB_Timer = 0
} Else {
	WinMinimize, % "ahk_id " TAB_List%TAB_n%
	If (TAB_n = TAB_List)
		TAB_n = 1
	Else
		TAB_n++
	Goto TAB_Activate
}
Return

$ScrollLock::
If GetKeyState("PrintScreen", "P") {
	If Not WinActive("ahk_class WorkerW")
		Send #d
} Else {
	Gosub TAB_CheckWindows
	If (TAB_List < 2) {
		If TAB_List
			WinActivate, ahk_id %TAB_List1%
		SoundPlay %A_Windir%\Media\Windows Ding.wav
		TAB_Timer = 0
	} Else {
		If (TAB_n = 1)
			TAB_n := TAB_List
		Else
			TAB_n--
		Goto TAB_Activate
	}
}
Return

TAB_CheckWindows:
WinGet, TAB_ListNew, List
TAB_ListNewLegit := TAB_ListNew
Loop %Tab_ListNew%
	If CheckLegitWindow(TAB_ListNew%A_Index%, 0)
		TAB_ListNewLegit--
	Else If Not InStr(TAB_ListString, TAB_ListNew%A_Index%)
		Goto TAB_GetWindows
StringReplace, TAB_ListString, TAB_ListString, x, x, All, UseErrorLevel
If (ErrorLevel <> TAB_ListNewLegit) or Not (TAB_Timer or WinActive("ahk_id " TAB_List%TAB_n%))
	Goto TAB_GetWindows
Return

TAB_GetWindows:
TAB_ListString =
Tab_ListTotal := TAB_ListNew
TAB_List = 0
TAB_n = 0
Loop %Tab_ListNew%
	If Not CheckLegitWindow(TAB_ListNew%A_Index%, 0) {
		TAB_List++
		TAB_List%TAB_List% := TAB_ListNew%A_Index%
		TAB_ListString := TAB_ListString TAB_ListNew%A_Index%
		If WinActive("ahk_id " TAB_ListNew%A_Index%)
			TAB_n := TAB_List
	}
Return

TAB_Activate:
WinActivate, % "ahk_id " TAB_List%TAB_n%
WinGet, TAB_mm, MinMax, % "ahk_id " TAB_List%TAB_n%
If (TAB_mm = 1)
	TAB_x := 0, TAB_y := 0, TAB_w := A_ScreenWidth, TAB_h := A_ScreenHeight
Else
	WinGetPos, TAB_x, TAB_y, TAB_w, TAB_h, % "ahk_id " TAB_List%TAB_n%
If (A_ThisHotkey = "$PrintScreen") and (TAB_Gui <> 1) {
	TAB_Gui := CreateBox("33FF99")
	TAB_Gui = 1
} Else If (A_ThisHotkey = "$ScrollLock") and (TAB_Gui <> -1) {
	TAB_Gui := CreateBox("3366CC")
	TAB_Gui = -1
}
Box(TAB_x, TAB_y, TAB_w, TAB_h, 8, "In")
SetTimer, TAB_Gui, -200
TAB_Timer = 1
SetTimer, TAB_Timer, -2000
If (A_ThisHotkey = "$PrintScreen")
	KeyWait, PrintScreen
Return

TAB_Gui:
RemoveBox()
TAB_Gui =
Return

TAB_Timer:
TAB_Timer =
Return

Box(XCor, YCor, Width, Height, Thickness, Offset) ;offset = In<n> or Out<n>
{
	If InStr(Offset, "In") {
		StringTrimLeft, offset, offset, 2
		If not Offset
			Offset = 0
		Side = -1
	} Else {
		StringTrimLeft, offset, offset, 3
		If not Offset
			Offset = 0
		Side = 1
	}
	x := XCor - (Side + 1) / 2 * Thickness - Side * Offset
	y := YCor - (Side + 1) / 2 * Thickness - Side * Offset
	h := Height + Side * Thickness + Side * Offset * 2
	w := Thickness
	Gui 81:Show, x%x% y%y% w%w% h%h% NA
	x += Thickness
	w := Width + Side * Thickness + Side * Offset * 2
	h := Thickness
	Gui 82:Show, x%x% y%y% w%w% h%h% NA
	x := x + w - Thickness
	y += Thickness
	h := Height + Side * Thickness + Side * Offset * 2
	w := Thickness
	Gui 83:Show, x%x% y%y% w%w% h%h% NA
	x := XCor - (Side + 1) / 2 * Thickness - Side * Offset
	y += h - Thickness
	w := Width + Side * Thickness + Side * Offset * 2
	h := Thickness
	Gui 84:Show, x%x% y%y% w%w% h%h% NA
}

CreateBox(Color="FF0000")
{
	Gui 81:color, %Color%
	Gui 81:+ToolWindow -SysMenu -Caption +AlwaysOnTop
	Gui 82:color, %Color%
	Gui 82:+ToolWindow -SysMenu -Caption +AlwaysOnTop
	Gui 83:color, %Color%
	Gui 83:+ToolWindow -SysMenu -Caption +AlwaysOnTop
	Gui 84:color, %Color%
	Gui 84:+ToolWindow -SysMenu -Caption +AlwaysOnTop
}

RemoveBox()
{
	Gui 81:destroy
	Gui 82:destroy
	Gui 83:destroy
	Gui 84:destroy
}

CheckLegitWindow(WindowToClose, CheckLegitChildWindow) ;a 1 will ALLOW dialog boxes (class #32770)
{
	WinGetClass, Class, ahk_id %WindowToClose%
	If Not Class
		Return "null"
	Else If (Class = "Shell_TrayWnd") or (Class = "WorkerW") or (Class = "IME") or (Class = "TpHotkeyOnscreen") or (Class = "TaskListThumbnailWnd") or (Class = "tooltips_class32") or (Class = "Progman") or (Class = "ClockFlyoutWindow") or ((Class = "#32770") and (CheckLegitChildWindow = "0")) or (Class = "Button") or (Class = "ThunderRT6Main") or (Class = "#32768") or (Class = "#32769") or (Class = "#32771") or (Class = "#32772") or (Class = "Button") or (Class = "DV2ControlHost") or (Class = "AutoHotkeyGUI") or (Class = "TaskSwitcherWnd")
		Return Class
	Else
		Return
}


#2 bruno

bruno
  • Members
  • 161 posts

Posted 26 March 2011 - 06:38 AM

Since I am a newbie, any side-effects running this script (I haven't tried it yet AND you mentioned, "This screws things up.")? :lol: :arrow: :?:

#3 berban

berban
  • Members
  • 180 posts

Posted 26 March 2011 - 06:40 AM

No, I meant that I took that feature out cause it screws things up :)

#4 Chicken Pie 4 Tea

Chicken Pie 4 Tea
  • Members
  • 377 posts

Posted 26 March 2011 - 09:04 AM

does it have the capacity to exclude a window from the process. I use for instance a program called quicknote wich is always running minimized and I dont want it being part of the alt/tab process. Other alt tab scripts I have tried from here have the capacity to exlude.

#5 berban1

berban1
  • Guests

Posted 26 March 2011 - 04:38 PM

Hey HelloWorld -

Yes that is definitely a possibility. See the function "CheckLegitWindow"?

CheckLegitWindow(WindowToClose, CheckLegitChildWindow) ;a 1 will ALLOW dialog boxes (class #32770) 
{ 
   WinGetClass, Class, ahk_id %WindowToClose% 
   If Not Class 
      Return "null" 
   Else If (Class = "Shell_TrayWnd") or (Class = "WorkerW") or (Class = "IME") or (Class = "TpHotkeyOnscreen") or (Class = "TaskListThumbnailWnd") or (Class = "tooltips_class32") or (Class = "Progman") or (Class = "ClockFlyoutWindow") or ((Class = "#32770") and (CheckLegitChildWindow = "0")) or (Class = "Button") or (Class = "ThunderRT6Main") or (Class = "#32768") or (Class = "#32769") or (Class = "#32771") or (Class = "#32772") or (Class = "Button") or (Class = "DV2ControlHost") or (Class = "AutoHotkeyGUI") or (Class = "TaskSwitcherWnd") 
      Return Class 
   Else 
      Return 
}

This incorporates many window classes that aren't "legit", for lack of a better word - examples are the start menu, tooltips, the task switcher window, etc. The easiest thing would be if your program had a unique window class, then you could just add the code
or (Class = "YourClass")
to the end of that function. Otherwise it'd be a bit more complicated but still easy.

If you do a lot of windowing tasks with AHK like I do, I would definitely recommend keeping a function like this in your library - otherwise you'll be forever accidentally messing with dumb system windows you didn't even know existed :p

#6 Chicken Pie 4 Tea

Chicken Pie 4 Tea
  • Members
  • 377 posts

Posted 26 March 2011 - 07:33 PM

Thanks for the reply, I should have looked through the code myself, yes I can see it would be easy to add stuff to exclude. thanks