change Quick Launch icon size (to small / large) on the fly?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
madscijr
Posts: 9
Joined: 26 May 2017, 12:20

change Quick Launch icon size (to small / large) on the fly?

26 May 2017, 16:34

I originally sought a solution for this using vbscript, which has been my Windows automation tool. Not finding an answer had me look into other solutions, which led to AutoHotKey, which seems to be quite capable of a good many things.

This is for a Windows 10 laptop (MS Surface Pro 3) configured with the quick launch menu.

Depending on whether the PC is attached to an external display or not, the size of the quick launch icons changes. Windows 10 doesn't seem to handle scaling the display very well automatically:
  • External display resolution is 2048x1152. When this display is attached, the quick launch icons are giant, and need to be set to Small.
  • Laptop display resolution is 2160x1440. When no external display is attached, the quick launch icons are miniscule, and need to be set to Large.
Changing the quick launch icon size can be accomplished manually, specifically with these steps:
To change icons small, you need to first unlock the Taskbar,
as the Quick Launch options are only visible
when you right click an empty spot inside Quick Launch area on an unlocked Taskbar
  • Unlock the taskbar
  • right click an empty spot INSIDE the Quick Launch area
  • from the resulting menu click View > Large Icons, or View > Small Icons
Would it be possible to automate changing the icon size with a script, e.g. accomplish the same as right-clicking inside the quick launch area and clicking View > Large/Small Icons ?

I found some threads where they discussed accomplishing this by setting the registry, but that would require a reboot, and this needs to be done on the fly.

Evidently it is possible to modify the quick launch toolbar from vbscript, at least adding items, for example: So could the icon size be changed on the fly from vbscript AutoHotKey?

Any help would be most appreciated...
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: change Quick Launch icon size (to small / large) on the fly?

27 May 2017, 01:56

Changing folder bands' icon sizes programmatically (without doing stuff like right-clicking on the toolbar and selecting the menu option - this works without needing to unlock the taskbar first) needs to be done on the same thread the toolbar window was created on, inside Explorer.exe. Here's such a hack that accomplishes that.

I only have a single monitor here - I don't know how well this works under multi-monitor environments, esp. with Windows 10 adding additional toolbars to secondary monitors.

Grab AutoHotkey_H v1 from https://hotkeyit.github.io/v2/

If you're using 64-bit Windows, extract x64w somewhere. If you're using 32-bit Windows, extract Win32w somewhere. Inside the extracted folder, download all of the following into it:

_Struct.ahk (open this file and remove the #Include <sizeof> line)
sizeof.ahk
InjectAhkDll.ahk (open this file and change Struct(_MODULEENTRY32) to new _Struct(_MODULEENTRY32))

Code: Select all

#NoEnv
#Persistent
#NoTrayIcon
SetBatchLines, -1
;DetectHiddenWindows On

main(), return

main()
{
	global WM_SETQUICKLAUNCHICONSIZE := DllCall("RegisterWindowMessage", "Str", "CARJACKCHIRAQ", "UInt"), msgHookCb, msgHook

	if ((msgHookCb := RegisterCallback("GetMsgProc", "Fast"))) {
		OnExit("AtExit")
		if ((hWnd := WinExist("ahk_class Shell_TrayWnd ahk_pid " . DllCall("GetCurrentProcessId", "UInt"))) && (tId := DllCall("GetWindowThreadProcessId", "Ptr", hWnd, "Ptr", 0, "UInt")))
			msgHook := DllCall("SetWindowsHookEx", "Int", WH_GETMESSAGE := 3, "Ptr", msgHookCb, "Ptr", 0, "UInt", tId, "Ptr")
	}
}

AtExit()
{
	global msgHook, msgHookCb
	OnExit(A_ThisFunc, 0)
	
	if (msgHook)
		DllCall("UnhookWindowsHookEx", "Ptr", msgHook), msgHook := 0

	if (msgHookCb)
		DllCall("GlobalFree", "Ptr", msgHookCb, "Ptr"), msgHookCb := 0

	return 0
}

GetMsgProc(nCode, wParam, lParam)
{
	Critical 999
	global msgHookCb, WM_SETQUICKLAUNCHICONSIZE
	static IID_IShellFolderBand
	PassToChain := True

	if (nCode >= 0) { ; HC_ACTION
		;hWnd := NumGet(lParam+0,, "Ptr")
		message := NumGet(lParam+0, A_PtrSize, "UInt")
		;msgLparam := NumGet(lParam+0, A_PtrSize * 3, "Ptr")
		;time := NumGet(lParam+0, A_PtrSize * 4, "UInt")
		;pt := NumGet(lParam+0, A_PtrSize * 5, "Int64")

		if (message == WM_SETQUICKLAUNCHICONSIZE) {
			msgWparam := NumGet(lParam+0, A_PtrSize * 2, "Ptr")
			PassToChain := False
			try if ((bandoSite := ComObjCreate("{F60AD0A0-E5E1-45cb-B51A-E15B9F8B2934}", "{4CF504B0-DE96-11D0-8B3F-00A0C911E8E5}"))) {
				VarSetCapacity(bandName, 522)
				bandoCount := DllCall(NumGet(NumGet(bandoSite+0)+4*A_PtrSize), "Ptr", bandoSite, "UInt", -1, "UInt*", 0)
				Loop %bandoCount% {
					if (DllCall(NumGet(NumGet(bandoSite+0)+4*A_PtrSize), "Ptr", bandoSite, "UInt", A_Index - 1, "UInt*", bandId) == 0) {
						if (DllCall(NumGet(NumGet(bandoSite+0)+5*A_PtrSize), "Ptr", bandoSite, "UInt", bandId, "Ptr", 0, "Ptr", 0, "WStr", bandName, "Int", 260) == 0) {
							if (bandName == "Quick Launch") {
								if (!VarSetCapacity(IID_IShellFolderBand))
									VarSetCapacity(IID_IShellFolderBand, 16), DllCall("ole32\CLSIDFromString", "WStr", "{7fe80cc8-c247-11d0-b93a-00a0c90312e1}", "Ptr", &IID_IShellFolderBand)
								if (DllCall(NumGet(NumGet(bandoSite+0)+8*A_PtrSize), "Ptr", bandoSite, "UInt", bandId, "Ptr", &IID_IShellFolderBand, "Ptr*", folderBand) == 0) {
									VarSetCapacity(BANDINFOSFB, 48, 0), NumPut(0x00000004, BANDINFOSFB,, "UInt")
									if (DllCall(NumGet(NumGet(folderBand+0)+5*A_PtrSize), "Ptr", folderBand, "Ptr", &BANDINFOSFB) == 0) {
										try if ((ctxMenu := ComObjQuery(folderBand, "{000214e4-0000-0000-c000-000000000046}"))) {
											VarSetCapacity(cmdInfo, cb := 56, 0), NumPut(cb, cmdInfo,, "UInt")
											newVal := NumGet(BANDINFOSFB, 24, "UShort")
											if (msgWparam > 0 && msgWparam < 3)
												newVal := msgWparam
											NumPut(newVal & 0xFFFF, cmdInfo, A_PtrSize == 8 ? 16 : 12, "Ptr")
											DllCall(NumGet(NumGet(ctxMenu+0)+4*A_PtrSize), "Ptr", ctxMenu, "Ptr", &cmdInfo)
											ObjRelease(ctxMenu)
										}
									}
									ObjRelease(folderBand)
								}
								break
							}
						}
					}
				}
				ObjRelease(bandoSite)
			}
		}
	}

	if (PassToChain) {
		return DllCall("CallNextHookEx", "Ptr", msgHookCb, "Int", nCode, "Ptr", wParam, "Ptr", lParam, "Ptr")
	} else {
		NumPut(0, lParam+0, A_PtrSize, "UInt") ; write WM_NULL into the MSG structure
		return True ; return 1 to stop further hooks from processing the message
	}
}

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#Include %A_ScriptDir%\sizeof.ahk
#Include %A_ScriptDir%\_Struct.ahk
#Include %A_ScriptDir%\InjectAhkDll.ahk

WM_TASKBARCREATED := DllCall("RegisterWindowMessage", "Str", "TaskbarCreated", "UInt")
,DllCall("ChangeWindowMessageFilterEx", "Ptr", A_ScriptHwnd, "UInt", WM_TASKBARCREATED, "UInt", MSGFLT_ALLOW := 1, "Ptr", 0)

Inject()
,OnMessage(WM_TASKBARCREATED, "OnTaskbarCreated")
,OnExit("AtExit")

OnTaskbarCreated()
{
	global rThread
	rThread := ""
	SetTimer Inject, -100
}

Inject()
{
	global rThread
	WinGet, nPid, PID, ahk_class Shell_TrayWnd
	if (nPid)
		rThread := InjectAhkDll(nPid, A_ScriptDir . "\AutoHotkeyMini.dll", "#Include " . A_ScriptDir . "\hook.ahk")
}
			
AtExit()
{
	OnExit(A_ThisFunc, 0)
	global rThread

	if (IsObject(rThread)) {
		rThread.Exec("Exit")
		rThread := ""
		Sleep -1
	}
	
	return 0
}
Run loader.ahk. If all went well, you can do the following from another script to change the icon size of the QL toolbar:

Code: Select all

#NoTrayIcon
#NoEnv

WM_SETQUICKLAUNCHICONSIZE := DllCall("RegisterWindowMessage", "Str", "CARJACKCHIRAQ", "UInt")
PostMessage %WM_SETQUICKLAUNCHICONSIZE%, 0,,, ahk_class Shell_TrayWnd
Posting 0 as the wParam causes the hook function to alternate between the two available icon settings; using 1 forces large icons and 2 small icons.

loader.ahk ensures AutoHotkey is injected into Explorer.exe every time Explorer restarts. The hook does not persist between sessions: If you log off/reboot, and loader.ahk is not set to run on start up, then there will be no trace of AutoHotkey inside Explorer. hook.ahk assumes your Quick Launch toolbar is called Quick Launch - change if needed.
madscijr
Posts: 9
Joined: 26 May 2017, 12:20

Re: change Quick Launch icon size (to small / large) on the fly?

30 May 2017, 10:33

That is a little more info than I can digest right now, but thanks for taking the time to answer. I will give this a try when I have more time, and let you know how it went.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 194 guests