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.