alt-tab replacement

Post your working scripts, libraries and tools
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

alt-tab replacement

18 Sep 2017, 10:00

An alt-tab replacement. The main principles are as follows:
- As with the standard alt-tab window, the window title of the selected item should appear at the top of the window. This is a flaw in other alt-tab replacements.
- Option to include/exclude show visible windows.
- Option to include/exclude show desktop.
- Option to include/exclude separate items for each Internet Explorer tab.
- Option to include/exclude an item that opens a new Internet Explorer window.

To be honest, I don't know if I will actually use this, perhaps if I can emulate the existing alt-tab window more closely (i.e. get the rows of icons), but with a listview underneath then I would. As it is, I might assign this a different hotkey, and use it as a secondary alt-tab window.

Code: Select all

;Alt-Tab Replacement by jeeswg

#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook

SplitPath, A_ScriptName,,,, vScriptNameNoExt
Menu, Tray, Tip, % vScriptNameNoExt

;==================================================

;options:
;the order in which items will appear
;specify zero to exclude an item
vListVisibleWindows := 1
vListIntExpTabs := 2
vListDesktop := 3
vListNewIntExp := 4

;==================================================

vListCount := 4
;hIcon := DllCall("user32\LoadIcon", Ptr,0, Ptr,32512, Ptr) ;IDI_APPLICATION := 32512
;get Desktop icon (tested on Windows 7)
hIconDT := LoadPicture("shell32.dll", "w16 h16 icon35", vType)
hIconDTBig := LoadPicture("shell32.dll", "w32 h32 icon35", vType)
;get Internet Explorer icon
hIconIE := LoadPicture("C:\Program Files\Internet Explorer\iexplore.exe", "w16 h16", vType)
hIconIEBig := LoadPicture("C:\Program Files\Internet Explorer\iexplore.exe", "w32 h32", vType)

Gui, New, +HwndhGui -Caption Border, Alt-Tab Replacement
Gui, Font, s16
Gui, Color, ABCDEF
Gui, Add, Picture, +HwndhStcImg x4 y4 w32 h32 +0x3 ;SS_ICON := 0x3
;Gui, Add, Picture, +HwndhStcImg x10 y10 w16 h16 +0x3 ;SS_ICON := 0x3
Gui, Add, Text, +HwndhStc x40 y6 w500
Gui, Add, ListView, -Hdr x-2 y40 w530 h280, Window Title
return

;==================================================

GuiClose:
ExitApp
return

;==================================================

!Tab::
+!Tab::
vIndex += InStr(A_ThisHotkey, "+")?-1:1
Gui, % hGui ":Default"

if !DllCall("user32\IsWindowVisible", "Ptr",hGui)
{
	;==============================
	Hotkey, IfWinActive, % "ahk_id " hGui
	Hotkey, *Esc, DoCancel, On
	LV_Delete(), IL_Destroy(hIL)
	hIL := IL_Create(30) ;small icons
	;hIL := IL_Create(30, 30, 1) ;large icons
	LV_SetImageList(hIL)
	vCount := 0, vPrompt := "", oHWnd := {}, oTitle := {}, oHIcon := {}, oHIconBig := {}
	Loop % vListCount
	{
		if (A_Index = vListVisibleWindows)
		{
			DetectHiddenWindows, Off
			WinGet, vWinList, List
			Loop % vWinList
			{
				hWnd := vWinList%A_Index%
				if !JEE_WinHasAltTabIcon(hWnd)
					continue
				WinGetTitle, vWinTitle, % "ahk_id " hWnd
				vCount += 1
				oHWnd.Push(hWnd)
				oTitle.Push(vWinTitle)
				oHIcon.Push(JEE_WinGetIcon(hWnd))
				oHIconBig.Push(JEE_WinGetIcon(hWnd, 1))
				IL_Add(hIL, "HICON:" oHIcon[vCount])
				LV_Add("Icon" vCount, vWinTitle)
			}
			DetectHiddenWindows, On
		}
		if (A_Index = vListDesktop)
		{
			vCount += 1
			oHWnd.Push("Desktop")
			oTitle.Push("Desktop")
			oHIcon.Push(hIconDT)
			oHIconBig.Push(hIconDTBig)
			IL_Add(hIL, "HICON:*" oHIcon[vCount])
			LV_Add("Icon" vCount, oTitle[vCount])
		}
		if (A_Index = vListIntExpTabs)
		{
			WinGet, vWinList, List, ahk_class TabThumbnailWindow
			Loop % vWinList
			{
				hWnd := vWinList%A_Index%
				WinGetTitle, vWinTitle, % "ahk_id " hWnd
				if (vWinTitle = "Blank Page - Internet Explorer")
				|| !(vWinTitle ~= " - Internet Explorer$")
					continue
				vCount += 1
				oHWnd.Push(hWnd)
				oTitle.Push(vWinTitle)
				oHIcon.Push(JEE_WinGetIcon(hWnd))
				;oHIconBig.Push(JEE_WinGetIcon(hWnd, 1))
				;the icons retrieved are small, therefore enlarge them:
				hIcon := JEE_WinGetIcon(hWnd, 1)
				hIcon := LoadPicture("HICON:" hIcon, "w32 h32", vType)
				oHIconBig.Push(hIcon)
				IL_Add(hIL, "HICON:" oHIcon[vCount])
				LV_Add("Icon" vCount, vWinTitle)
			}
		}
		if (A_Index = vListNewIntExp)
		{
			vCount += 1
			oHWnd.Push("NewIntExp")
			oTitle.Push("New Internet Explorer Window")
			oHIcon.Push(hIconIE)
			oHIconBig.Push(hIconIEBig)
			IL_Add(hIL, "HICON:*" oHIcon[vCount])
			LV_Add("Icon" vCount, oTitle[vCount])
		}
	}
	;Loop 2
	;	LV_Add("Icon0", "")
	;==============================
	vIndex := 2
	Gui, Show, y250 w500 h300
	SetTimer, CheckAlt, 30
}
if (vIndex < 1)
	vIndex := vCount
if (vIndex > vCount)
	vIndex := 1
ControlSetText,, % oTitle[vIndex], % "ahk_id " hStc
SendMessage, 0x170, % oHIconBig[vIndex], 0,, % "ahk_id " hStcImg ;STM_SETICON := 0x170
;SendMessage, 0x170, % oHIcon[vIndex], 0,, % "ahk_id " hStcImg ;STM_SETICON := 0x170

;LV_Modify(vIndex, "Focus")
LV_Modify(0, "-Select")
LV_Modify(vIndex, "Select")
LV_Modify(vIndex, "Vis")
return

;==================================================

CheckAlt:
if !GetKeyState("Alt", "P")
{
	SetTimer, CheckAlt, Off
	WinHide, % "ahk_id " hGui
	DetectHiddenWindows, On
	if (oHWnd[vIndex] = "Desktop")
		WinMinimizeAll
	else if (oHWnd[vIndex] = "NewIntExp")
		Run, iexplore.exe
	else
		WinActivate, % "ahk_id " oHWnd[vIndex]
}
return

;==================================================

DoCancel:
SetTimer, CheckAlt, Off
Hotkey, IfWinActive, % "ahk_id " hGui
Hotkey, *Esc, DoCancel, Off
WinHide, % "ahk_id " hGui
return

;==================================================

;JEE_WinGetHIcon
JEE_WinGetIcon(hWnd, vDoGetBig:=0)
{
	static vSfx := (A_PtrSize=8) ? "Ptr" : ""
	if !hWnd || !WinExist("ahk_id " hWnd)
		return 0
	if vDoGetBig
	{
		if (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",1, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_BIG := 1
		|| (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",0, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_SMALL := 0
		|| (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",2, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_SMALL2 := 2
		|| (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-14, "UPtr")) ;GCL_HICON := -14 ;(big icon)
		|| (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-34, "UPtr")) ;GCL_HICONSM := -34 ;(small icon)
		|| (hIcon := DllCall("user32\LoadIcon", "Ptr",0, "Ptr",32512, "Ptr")) ;IDI_APPLICATION := 32512 ;(standard exe icon)
			return hIcon
	}
	else
	{
		if (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",0, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_SMALL := 0
		|| (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",2, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_SMALL2 := 2
		|| (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",1, "Ptr",0, "Ptr")) ;WM_GETICON := 0x7F ;ICON_BIG := 1
		|| (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-34, "UPtr")) ;GCL_HICONSM := -34 ;(small icon)
		|| (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-14, "UPtr")) ;GCL_HICON := -14 ;(big icon)
		|| (hIcon := DllCall("user32\LoadIcon", "Ptr",0, "Ptr",32512, "Ptr")) ;IDI_APPLICATION := 32512 ;(standard exe icon)
			return hIcon
	}
	return 0
}

;==================================================

;info for: JEE_WinHasTaskbarButton/JEE_WinHasAltTabIcon

;will it appear on the alt-tab dialog/taskbar:
;WS_CHILD := 0x40000000 ;A maybe, T maybe (appears to make no difference re. presence on list, but does affect the alt-tab icon's appearance)
;WS_VISIBLE := 0x10000000 ;(if off:) A no, T no
;WS_DISABLED := 0x8000000 ;A no, T maybe
;WS_EX_NOACTIVATE := 0x8000000 ;A no, T maybe
;WS_EX_APPWINDOW := 0x40000 ;A yes, T yes
;WS_EX_TOOLWINDOW := 0x80 ;A no, T no (T: under some conditions it seems you can have WS_EX_TOOLWINDOW and a taskbar button)
;has owner ;A maybe, T no
;has parent ;A no, T no
;note: WS_EX_APPWINDOW takes priority over WS_EX_TOOLWINDOW

;Window Styles | Microsoft Docs
;https://docs.microsoft.com/en-us/windows/desktop/winmsg/window-styles
;Extended Window Styles | Microsoft Docs
;https://docs.microsoft.com/en-us/windows/desktop/winmsg/extended-window-styles
;WS_EX_APPWINDOW:
;Forces a top-level window onto the taskbar when the window is visible.
;WS_EX_NOACTIVATE:
;The window does not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style.
;WS_EX_TOOLWINDOW:
;A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB.

;from the AHK documentation:
;An owned window has no taskbar button by default, and when visible it is always on top of its owner.

;script for testing:
;DetectHiddenWindows, On
;Gui, New, +HwndhGui -0xFFFFFFFF -E0xFFFFFFFF
;Gui, Show, W300 H300

;hWndParent := DllCall("user32\GetAncestor", Ptr,hWnd, UInt,1, Ptr) ;GA_PARENT := 1
;hWndOwner := DllCall("user32\GetWindow", Ptr,hWnd, UInt,4, Ptr) ;GW_OWNER := 4

;example: WS_EX_TOOLWINDOW on and has no taskbar button
;DetectHiddenWindows, On
;Gui, New, +HwndhGui -0xFFFFFFFF -E0xFFFFFFFF +E0x80 ;WS_EX_TOOLWINDOW := 0x80
;Gui, Show, W300 H300

;example: WS_EX_TOOLWINDOW on but has a taskbar button
;DetectHiddenWindows, On
;Gui, New, +HwndhGui -0xFFFFFFFF -E0xFFFFFFFF
;Gui, Show, W300 H300
;WinSet, ExStyle, +0x80, % "ahk_id " hGui ;WS_EX_TOOLWINDOW := 0x80

;==================================================

;gives you roughly the correct results (tested on Windows 7)
;JEE_WinIsTaskbar
JEE_WinHasTaskbarButton(hWnd)
{
	local
	if !(DllCall("user32\GetDesktopWindow", "Ptr") = DllCall("user32\GetAncestor", "Ptr",hWnd, "UInt",1, "Ptr")) ;GA_PARENT := 1
	|| DllCall("user32\GetWindow", "Ptr",hWnd, "UInt",4, "Ptr") ;GW_OWNER := 4 ;affects taskbar but not alt-tab
		return 0
	if DllCall("user32\GetWindow", "Ptr",hWnd, "UInt",4, "Ptr") ;GW_OWNER := 4 ;affects taskbar but not alt-tab
		return 0
	WinGet, vWinStyle, Style, % "ahk_id " hWnd
	if !vWinStyle
	|| !(vWinStyle & 0x10000000) ;WS_VISIBLE := 0x10000000
	;|| (vWinStyle & 0x8000000) ;WS_DISABLED := 0x8000000 ;affects alt-tab but not taskbar
		return 0
	WinGet, vWinExStyle, ExStyle, % "ahk_id " hWnd
	if (vWinExStyle & 0x40000) ;WS_EX_APPWINDOW := 0x40000
		return 1
	;under some conditions it seems you can have WS_EX_TOOLWINDOW and a taskbar button
	if (vWinExStyle & 0x80) ;WS_EX_TOOLWINDOW := 0x80
	;|| (vWinExStyle & 0x8000000) ;WS_EX_NOACTIVATE := 0x8000000 ;affects alt-tab but not taskbar
		return 0
	return 1
}

;==================================================

;gives you roughly the correct results (tested on Windows 7)
;JEE_WinIsAltTab
JEE_WinHasAltTabIcon(hWnd)
{
	local
	if !(DllCall("user32\GetDesktopWindow", "Ptr") = DllCall("user32\GetAncestor", "Ptr",hWnd, "UInt",1, "Ptr")) ;GA_PARENT := 1
	;|| DllCall("user32\GetWindow", "Ptr",hWnd, "UInt",4, "Ptr") ;GW_OWNER := 4 ;affects taskbar but not alt-tab
		return 0
	WinGet, vWinStyle, Style, % "ahk_id " hWnd
	if !vWinStyle
	|| !(vWinStyle & 0x10000000) ;WS_VISIBLE := 0x10000000
	|| (vWinStyle & 0x8000000) ;WS_DISABLED := 0x8000000 ;affects alt-tab but not taskbar
		return 0
	WinGet, vWinExStyle, ExStyle, % "ahk_id " hWnd
	if (vWinExStyle & 0x40000) ;WS_EX_APPWINDOW := 0x40000
		return 1
	if (vWinExStyle & 0x80) ;WS_EX_TOOLWINDOW := 0x80
	|| (vWinExStyle & 0x8000000) ;WS_EX_NOACTIVATE := 0x8000000 ;affects alt-tab but not taskbar
		return 0
	return 1
}

;==================================================
LINKS:

[The best alt-tab replacement I had found in the past, I didn't use any code from it, but I liked the way it looked, it was the closest, of any alt-tab replacements that I found, to what I had in mind:]
ALT-TAB replacement with icons and window titles in ListView - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/6010-alt-tab-replacement-with-icons-and-window-titles-in-listview/
"ALT-TAB REPLACEMENT (WITH ICONS AND WINDOW TITLES IN A LISTVIEW)." - Google Search
https://www.google.com/search?q=%22ALT-TAB+REPLACEMENT+%28WITH+ICONS+AND+WINDOW+TITLES+IN+A+LISTVIEW%29.%22

[This script was useful to create an icon, that I could use with AHK's LoadPicture and WM_SETICON in order to confirm that my alt-tab replacement was showing the entirety of a large 32x32 icon, and not missing out any pixels:]
ICO creater/converter (.PNG to .ICO) - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/82416-ico-createrconverter-png-to-ico/
AutoHotkey/ICO Converter.ahk at master · Qetuoadgj/AutoHotkey · GitHub
https://github.com/Qetuoadgj/AutoHotkey/blob/master/ICO%20Converter.ahk

[2000th post]
Last edited by jeeswg on 30 Nov 2019, 11:49, edited 4 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4678
Joined: 17 Jul 2016, 01:02
Contact:

Re: alt-tab replacement

18 Sep 2017, 16:39

Seems to work well, nice one! Thanks for sharing. :thumbup:
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: alt-tab replacement

15 Nov 2018, 14:07

- I've tried to look further into identifying which windows appear in the alt-tab list and taskbar. I would very much welcome any feedback.
- Such information is useful in order to recreate the lists, but is also useful in order to deliberately include/exclude a window from the alt-tab list/taskbar.
- [EDIT:] Updated JEE_WinHasAltTabIcon/JEE_WinHasTaskbarButton functions above.
Last edited by jeeswg on 17 Nov 2018, 05:36, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Thoughtfu1Tux
Posts: 123
Joined: 31 May 2018, 23:26

Re: alt-tab replacement

17 Nov 2018, 01:21

Thanks for the share. I use the a High Contrast based theme on windows 7, and this is much more useful than the icon switcher that shows up when I alt tab currently.

How can i use the code in your second post to provide feedback? I'm a fairly beginner level programmer and the stuff in the second post is a bit over my head.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: alt-tab replacement

17 Nov 2018, 05:32

- Thanks. AFAIK there isn't a simple way to get a list of windows that appear in the alt-tab or taskbar lists, therefore you have to reverse-engineer it. I attempt this by using WinGet, vWinList, List, to get a list of top-level windows, and by using one of my 2 filter functions to filter that list.
- Any feedback would consist of information about any windows that my filter wrongly included or excluded when trying to recreate the alt-tab/taskbar lists.
- Also, feedback re. the WS_EX_TOOLWINDOW/taskbar button anomaly that I mention, would be useful.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Thoughtfu1Tux
Posts: 123
Joined: 31 May 2018, 23:26

Re: alt-tab replacement

08 Dec 2018, 19:15

Been using this for about 3 weeks now and it has performed incredibly well.
Today I found a bug that I'm not sure how I would go at fixing.
When I have the Spotify program open and use Alt-Tab, Spotify has two spots on the list. The first one is just empty, with no name or icon, and the second one is Spotify itself.

If i'm swithing from another program, like Firefox or Windows explorer, and I alt-Tab to the empty option and select it, it will switch the window to Spotify, just like if I were to select Spottily from the list.

When i tried to use WindowSpy, I got the same result when i tried to Alt-Tab to either of the options. So I think it is just listing two different options, when there is only 1 window open.

Let me know if there's any other info that I can give about the issue.


Image
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: alt-tab replacement

08 Dec 2018, 19:25

- @Thoughtfu1Tux: Thanks for your input.
- Everything depends on this function: JEE_WinHasAltTabIcon. I've tried my best to correctly identify which windows would appear in the alt-tab window, and recreate that.
- Btw you could check that you are using the most up-to-date version, I updated the post on 17 Nov 2018.
- For a quick fix: you could add a check to the function based on the window's class and title to exclude that specific window, with at least one comment indicating that the function has been modified. You could also check the window style/ex. style. (So you'd want to use commands like WinGetClass, WinGetTitle, WinGetStyle, WinGetExStyle.)
- For a permanent solution: you'd need to look at and understand the function, and do some experiments, and see if you could figure out a way to improve the function.
- A further point, it would be useful to know what OS you're using, it's possible that different OSes use different criteria. Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Scripts and Functions”

Who is online

Users browsing this forum: oldbrother and 17 guests