Jump to content
  • 0

Classic Alt Tab (Reincarnation)


meebers

Question

Here is a fully revised classic Alt Tab Reincarnation. You can set the following configurations via right-clicking the tray icon:
1757815603325.webp

Toast Notifications for Confirmation of tray menu changes:
1757818727874.webp

Squared:
1757861206730.webp

Rounded:
1757815896473.webp

Original Classic Alt+Tab for Comparison:
1746492212904.webp
This iteration:

1) shows on screen that cursor is on
2) ctrl alt tab keeps gui open until selection is made
a) can navigate via mouse, arrows or tab/shift tab
b) can select via mouse, space or enter
3) tray menu right click has:
Light / Dark mode toggle < when applied, highlight outline is default blue
Use Accent Color < when applied, highlight outline is white; if you change the accent color, REAPPLY this from menu to apply to GUI.
Rounded / Squared Toggle
Show Ctrl+Alt+Tab persistent GUI
4) bottom row is left-aligned (did not remove your code, but commented out
5) Double Clicking Tray Icon shows Ctrl+Alt+Tab persistent GUI
6) Rows are 7 icons across and GUI expands vertically dynamically
7) Toast Notifications are displayed when changing color of GUI or corner styles

thanks to @das10 for work on this as well. helped quite a bit with it.

Code:
;;;
;;; if (!A_IsCompiled && !InStr(A_AhkPath, "_UIA")) {        ; ADDED to always run with UIA so hotkey works even if elevated window is in foreground (eg: Task Manager)
;;;     Run % "*uiAccess " A_ScriptFullPath                  ;  requires AHK 1 installed with the UIA option selected
;;;     ExitApp                                              ;    https://www.autohotkey.com/board/topic/70449-enable-interaction-with-administrative-programs/
;;; }

#SingleInstance Force
#NoEnv
#UseHook
SetBatchLines, -1
SetWinDelay, 0
SetKeyDelay, 0, 20
AutoTrim, Off
Process, Priority,, AboveNormal    ; RUN AT HIGH PRIORITY
OnMessage(0x404, "AHK_NOTIFYICON") ; WM_USER + 4

; ---------------------------------- Config ----------------------------------
; -------------------------Change configuration here--------------------------

; ------------------------- Tray Menu for Theme Switching -------------------------
Menu, Tray, UseErrorLevel
Menu, Tray, DeleteAll
Menu, Tray, NoStandard
Menu, Tray, Add, Light / Dark, ToggleThemeMode
Menu, Tray, Add, Use Accent Color, SetAccentColor
Menu, Tray, Add, Rounded / Squared, ToggleRoundedCorners
Menu, Tray, Add, Show AltTab GUI, ShowAltTabPersistent
Menu, Tray, Add, Exit, ExitScript
Menu, Tray, Click, 1
Menu, Tray, Default, ShowAltTabPersistent


iconsPerRow    := 7                ; icons shown per row
iconSize       := 32               ; 32 works best, any higher & anti-alias noticeable
spacing        := 12               ; "x-axis" & "y-axis" space between icons
padX           := 12               ; padding at Left & Right of GUI
padY           := 16               ; padding at Top & Bottom of GUI
PanelColor     := 0xDEDEDE         ; GUI background color use any in Hex Format or only an AHK allowable name color in quotes (see: https://www.autohotkey.com/docs/v2/misc/Colors.htm)
TitleColor     := "BLACK"          ; Title Color
HighLightColor := 0x004DFF ;0x80FFFF         ; visible highlight color (outer) Hot track

; Double-layer highlight config
highlightGap   := 4                ; px gap between icon and inner mask (the "air" you see)
highlightThk   := 2                ; thickness of outer visible highlight

; Title placement option - (do NOT use - option needs some more debugging)
TitleBelowRows := true             ; true = title below icons, false = title above

global ThemeMode := "Accent"  ; Default mode

if FileExist(A_ScriptDir "\theme.ini") {
    IniRead, ThemeMode, %A_ScriptDir%\theme.ini, Settings, ThemeMode, Accent
    IniRead, RoundedCorners, %A_ScriptDir%\theme.ini, Settings, RoundedCorners, 0
}

if (ThemeMode = "Light") {
    PanelColor := 0xDEDEDE
    TitleColor := "BLACK"
    HighLightColor := 0x004DFF
} else if (ThemeMode = "Dark") {
    PanelColor := 0x1E1E1E
    TitleColor := "WHITE"
    HighLightColor := 0x004DFF
} else if (ThemeMode = "Accent") {
    RegRead, accentColorHex, HKCU\Software\Microsoft\Windows\DWM, ColorizationColor
    rgb := accentColorHex & 0xFFFFFF
    r := (rgb >> 16) & 0xFF
    g := (rgb >> 8) & 0xFF
    b := rgb & 0xFF
    PanelColor := Format("0x{:02X}{:02X}{:02X}", r, g, b)

    brightness := 0.299 * r + 0.587 * g + 0.114 * b
    TitleColor := (brightness > 160) ? "BLACK" : "WHITE"

    hsl := RGBtoHSL(r, g, b)
    hue := hsl.h

    ; Set highlight to white for Accent Color GUI
        HighLightColor := "WHITE"
    } else {
        HighLightColor := "0x004DFF"
}

;----------- RGB for Accent Colored GUI -------------------------
RGBtoHSL(r, g, b) {
    r := r / 255.0
    g := g / 255.0
    b := b / 255.0

    max := Max(r, g, b)
    min := Min(r, g, b)
    h := s := l := (max + min) / 2

    if (max = min) {
        h := s := 0  ; achromatic
    } else {
        d := max - min
        s := (l > 0.5) ? d / (2 - max - min) : d / (max + min)

        if (max = r)
            h := (g - b) / d + (g < b ? 6 : 0)
        else if (max = g)
            h := (b - r) / d + 2
        else
            h := (r - g) / d + 4

        h := h * 60
    }

    return {h: h, s: s, l: l}
}

;----------- calculations - don't edit (unless you want to)! -------------------------
; Outer highlight size will be calculated below from iconSize + 2*(gap + thk)
highlightSize  := iconSize + 2*(highlightGap + highlightThk)

maxwidth       := (iconsPerRow * iconSize) + ((iconsPerRow - 1) * spacing) + (2 * padX)
maxWidth_Text  := maxwidth - (2 * padX)

; ---------------------------------- Custom Icon Map ----------------------------------
; --- user specified icons for UWP Windows (make your own, or use samples included)----
; --------------------- to add more, follow the examples below ------------------------
global CustomIcons := {}
CustomIcons["ApplicationFrameWindow: Calculator"]           := "Calculator.ico"
CustomIcons["ApplicationFrameWindow: Settings"]             := "Settings.ico"
CustomIcons["ApplicationFrameWindow: Camera"]               := "Camera.ico"
CustomIcons["ApplicationFrameWindow: Clock"]                := "Clock.ico"
CustomIcons["ApplicationFrameWindow: Windows Security"]     := "Defender.ico"
CustomIcons["#CLASS:ApplicationFrameWindow"]                := "Exe.ico"    ; fallback for AppFrame windows

; -------------------------------- Exclusions ----------------------------------------
; -----------exclude specific Windows (& their icons) from AltTab GUI-----------------
global ExcludedTitles  := []     ; exact/substring matches to exclude
global ExcludedClasses := []     ; classes to exclude

global ExcludedRules := []       ; array of Objects: Exe/Class/Title combos
; Example: exclude IrfanView fullscreen window by exe + class:
ExcludedRules.Push(Object("Exe", "i_view64.exe", "Class", "FullScreenClass"))
ExcludedRules.Push(Object("Exe", "XnViewMP.exe", "Title", " - XnView MP"))

; ---------------------------------- Globals ----------------------------------
global guiActive := false
global oHWnd := {}, oTitle := {}
global vCount := 0, vIndex := 0
global IconX := [], IconY := []
global IconCtrlHwnd := []   ; store HWNDs of picture controls for hover detection
global hWndGUI := 0
global persistentAltTab := false

~Alt::return

; ------------------------- Double Click Tray Show GUI -------------------------
ShowAltTabPersistent() {
    global persistentAltTab, guiActive, vCount, vIndex
    persistentAltTab := true
    if (!guiActive) {
        Gosub, BuildAltTabGui
        if (vCount = 0)
            return 
        vIndex := (vCount > 1) ? 2 : 1
        Gosub, UpdateHighlight
        SetTimer, CheckHover, 50
    }
}
return

; ---------------------------------- Tray Double Click ----------------------------------
AHK_NOTIFYICON(wParam, lParam)
{
    static WM_LBUTTONDBLCLK := 0x203
    if (lParam = WM_LBUTTONDBLCLK) {
        ShowAltTabPersistent()
    }
}

; ---------------------------------- Hotkeys ----------------------------------
!Tab::
    persistentAltTab := false
    if (!guiActive) {
        Gosub, BuildAltTabGui
        if (vCount = 0)
            return
        vIndex := (vCount > 1) ? 2 : 1   ; start on 2nd icon if available
    } else {
        vIndex++
        if (vIndex > vCount)
            vIndex := 1
    }
    Gosub, UpdateHighlight
return

$+!Tab::
    persistentAltTab := false
    if (!guiActive) {
        Gosub, BuildAltTabGui
        if (vCount = 0)
            return
        vIndex := vCount  ; start on last icon
    } else {
        vIndex--
        if (vIndex < 1)
            vIndex := vCount
    }
    Gosub, UpdateHighlight
return

^!Tab::
    persistentAltTab := true
    if (!guiActive) {
        Gosub, BuildAltTabGui
        if (vCount = 0)
            return
        vIndex := (vCount > 1) ? 2 : 1
    } else {
        vIndex++
        if (vIndex > vCount)
            vIndex := 1
    }
    Gosub, UpdateHighlight
    SetTimer, CheckHover, 50  ; <-- Add this line
return

Alt Up::
    if (persistentAltTab)
        return  ; Don't close GUI if Ctrl+Alt+Tab was used

    if (guiActive) {
        if (vIndex >= 1 && vIndex <= vCount)
            WinActivate, % "ahk_id " oHWnd[vIndex]
        SetTimer, CheckHover, Off
        Gui, AltTab:Hide
        guiActive := false
        persistentAltTab := false
        ForceModifierReset()
    }

return

Tab::
    if (guiActive || persistentAltTab) {
        vIndex++
        if (vIndex > vCount)
            vIndex := 1
        Gosub, UpdateHighlight
    } else {
        Send {Tab}
    }
return

+Tab::
    if (guiActive || persistentAltTab) {
        vIndex--
        if (vIndex > vCount)
            vIndex := 1
        Gosub, UpdateHighlight
    } else {
        Send +{Tab}
    }
return

#If (guiActive || persistentAltTab)
Tab::
    vIndex++
    if (vIndex > vCount)
        vIndex := 1
    Gosub, UpdateHighlight
return

+Tab::
    vIndex--
    if (vIndex < 1)
        vIndex := vCount
    Gosub, UpdateHighlight
return
#If

#If guiActive
Left::NavigateIcons("Left")
Right::NavigateIcons("Right")
Up::NavigateIcons("Up")
Down::NavigateIcons("Down")
#If

NavigateIcons(direction) {
    global vIndex, vCount, iconsPerRow

    if (direction = "Left") {
        vIndex--
        if (vIndex < 1)
            vIndex := vCount
    } else if (direction = "Right") {
        vIndex++
        if (vIndex > vCount)
            vIndex := 1
    } else if (direction = "Up") {
        vIndex -= iconsPerRow
        if (vIndex < 1)
            vIndex := vIndex + iconsPerRow * Ceil(vCount / iconsPerRow)
        if (vIndex > vCount)
            vIndex := vCount
    } else if (direction = "Down") {
        vIndex += iconsPerRow
        if (vIndex > vCount)
            vIndex := vIndex - iconsPerRow * Ceil(vCount / iconsPerRow)
        if (vIndex < 1)
            vIndex := 1
    }

    Gosub, UpdateHighlight
}
return

#If guiActive
Space::
Enter::
    if (vIndex >= 1 && vIndex <= vCount) {
        WinActivate, % "ahk_id " oHWnd[vIndex]
        SetTimer, CheckHover, Off
        Gui, AltTab:Hide
        guiActive := false
        persistentAltTab := false
        ForceModifierReset()
    }
return
#If

Esc::
    if (guiActive) {
        SetTimer, CheckHover, Off
        Gui, AltTab:Hide
        guiActive := false
        persistentAltTab := false
        ForceModifierReset()
    } else {
        Send {Esc}
    }
return

; ---------------------------------- GUI Builder ----------------------------------
BuildAltTabGui:
    oHWnd := {}, oTitle := {}, IconX := [], IconY := [], IconCtrlHwnd := []
    vCount := 0
    DetectHiddenWindows, Off
    WinGet, winList, List
    Loop % winList {
        hWnd := winList%A_Index%

        ; Quick Alt-Tab membership test
        if !JEE_WinHasAltTabIcon(hWnd)
            continue

        WinGetTitle, vWinTitle, ahk_id %hWnd%
        if (vWinTitle = "")
            continue

        WinGetClass, vClass, ahk_id %hWnd%
        WinGet, vProc, ProcessName, ahk_id %hWnd%

        ; arrays use .HasValue, but empty arrays won't match
        if (ExcludedTitles.HasValue && ExcludedTitles.HasValue(vWinTitle))
            continue
        if (ExcludedClasses.HasValue && ExcludedClasses.HasValue(vClass))
            continue

        ; exclusion rules (object array)
        for i, rule in ExcludedRules {
            matchExe   := !rule.HasKey("Exe")   || (rule.Exe   = vProc)
            matchClass := !rule.HasKey("Class") || (rule.Class = vClass)
            matchTitle := !rule.HasKey("Title") || (rule.Title = vWinTitle)
            if (matchExe && matchClass && matchTitle) {
                continue 2
            }
        }

        vCount++
        oHWnd[vCount]  := hWnd
        ; Prepend a space to titles to stay consistent with earlier matching logic
        oTitle[vCount] := " " . vWinTitle
    }
    DetectHiddenWindows, On

    if (vCount = 0)
        return

    Gui, AltTab:Destroy
    Gui, AltTab:New, +AlwaysOnTop -Caption +Owner +ToolWindow hwndhWndGUI +Border
    Gui, AltTab:Color, %PanelColor%
    Gui, AltTab:Margin, 0, 0

    ; Double-layer highlight controls (Disabled so they do not intercept mouse)
    ; Outer: visible highlight
    Gui, AltTab:Add, Progress, x0 y0 w%highlightSize% h%highlightSize% vOuterGlow -Smooth Background%HighLightColor% -Border Hidden Disabled
    ; Inner: mask filled with panel color to create "air gap"
    innerSize := iconSize + 2*highlightGap
    Gui, AltTab:Add, Progress, x0 y0 w%innerSize% h%innerSize% vInnerMask -Smooth Background%PanelColor% -Border Hidden Disabled

    ; Icons in rows
    x := padX, y := padY, rowHeight := iconSize + spacing
    Loop % vCount {
        idx := A_Index
        hLocal := oHWnd[idx]
        tLocal := oTitle[idx]
        WinGetClass, vClass, ahk_id %hLocal%
        WinGet, vProc, ProcessName, ahk_id %hLocal%

        IconX[idx] := x
        IconY[idx] := y

        opt := "x" x " y" y " w" iconSize " h" iconSize " hwndhCtl gOnIconClick vI" . idx

        ; --- Try custom icon resolver first ---
        path := GetCustomIconPath(vClass, tLocal, vProc)
        if (path != "") {
            Gui, AltTab:Add, Picture, %opt%, % path
        } else {
            ; Fallback: get real HICON from window
            hIcon := JEE_WinGetIcon(hLocal, 1)
            if !hIcon
                continue
            Gui, AltTab:Add, Picture, %opt%, % "HICON:" hIcon
        }

        ; store control HWND for hover detection
        GuiControlGet, hwndhCtl, Hwnd, I%idx%
        IconCtrlHwnd[idx] := hwndhCtl

        x += iconSize + spacing
        if (x + iconSize + padX > maxwidth) {
            x := padX
            y := y + rowHeight
        }
    }

    ; --- Center the last row if it has fewer icons than iconsPerRow ---
    ; Remove this block if you don't want to center the icons
    ;iconsPerRow_calc := Floor((maxwidth - padX*2 + spacing) / (iconSize + spacing))
    ;if (iconsPerRow_calc < 1)
        ;iconsPerRow_calc := 1

    ;lastRowCount := Mod(vCount, iconsPerRow_calc)
    ;if (lastRowCount = 0 && vCount >= iconsPerRow_calc)
        ;lastRowCount := iconsPerRow_calc
    ;if (lastRowCount > 0 && lastRowCount < iconsPerRow_calc) {
        ;usedWidth := (lastRowCount * (iconSize + spacing)) - spacing
        ;offsetX := ((maxwidth - 2*padX) - usedWidth) // 2
        ;Loop % lastRowCount {
            ;idx2 := vCount - lastRowCount + A_Index
            ;IconX[idx2] += offsetX
            ;GuiControl, AltTab:Move, I%idx2%, % "x" IconX[idx2] " y" IconY[idx2]
        ;}
    ;}

    ; --- calculate occupied rows and position title depending on TitleBelowRows ---
    rows := Ceil(vCount / iconsPerRow)
    if (TitleBelowRows) {
        ; Title below icons
        y := padY + rows * (iconSize + spacing) - spacing + (0.75 * padY)
        Gui, AltTab:Font, s10 w600 c%TitleColor%, Segoe UI Variable Display Semibol
        Gui, AltTab:Add, Text, x%padX% y%y% w%maxWidth_Text% h30 vTitleText +Border +0x80 +0x200 +0x4000 +0x1000,
        totalHeight := y + 40
    } else {
        ; Title above icons
        ; place title at top, push rows downward
        Gui, AltTab:Font, s10 w600 c%TitleColor%, Segoe UI Variable Display Semibol
        Gui, AltTab:Add, Text, x%padX% y%padY% w%maxWidth_Text% h30 vTitleText +Border +0x80 +0x200 +0x4000 +0x1000,
        ; shift icon area down by title height
        rowsAreaHeight := rows * (iconSize + spacing) - spacing
        totalHeight := padY + 30 + padY + rowsAreaHeight + padY  ; crude but safe
        ; re-calc row area start so highlight positions align (we used IconY previously so they should be fine)
    }
 
    CoordMode, Mouse, Screen
    MouseGetPos, mouseX, mouseY

    SysGet, monitorCount, MonitorCount
    Loop, %monitorCount% {
        SysGet, mon, Monitor, %A_Index%
        if (mouseX >= monLeft && mouseX <= monRight && mouseY >= monTop && mouseY <= monBottom) {
            screenX := monLeft + ((monRight - monLeft - maxwidth) // 2)
            screenY := monTop + ((monBottom - monTop - totalHeight) // 2)
            break
        }
    }

    Gui, AltTab:Show, % "x" screenX " y" screenY " w" maxwidth " h" totalHeight, Alt-Tab
    if (RoundedCorners) {
    rgn := CreateRoundRectRgn(0, 0, maxwidth, totalHeight, 20, 20)
    DllCall("SetWindowRgn", "Ptr", hWndGUI, "Ptr", rgn, "Int", true)
}
    guiActive := true

    SetTimer, CheckHover, 50  ; check mouse 20x/sec
return

CreateRoundRectRgn(left, top, right, bottom, width, height) {
    return DllCall("gdi32\CreateRoundRectRgn", "Int", left, "Int", top, "Int", right, "Int", bottom, "Int", width, "Int", height, "Ptr")
}

; ---------------------------------- Highlight + Title ----------------------------------
UpdateHighlight:
    if (vIndex < 1 || vIndex > vCount)
        return

    ; compute placement so outer fully surrounds inner mask by highlightThk
    ; outer top-left = IconX - (highlightGap + highlightThk)
    ox := IconX[vIndex] - (highlightGap + highlightThk)
    oy := IconY[vIndex] - (highlightGap + highlightThk)
    GuiControl, AltTab:Move, OuterGlow, % "x" ox " y" oy " w" highlightSize " h" highlightSize
    GuiControl, AltTab:Show, OuterGlow
    GuiControl, AltTab:MoveDraw, OuterGlow

    ; inner mask top-left = IconX - highlightGap
    ix := IconX[vIndex] - highlightGap
    iy := IconY[vIndex] - highlightGap
    innerSize := iconSize + 2*highlightGap
    GuiControl, AltTab:Move, InnerMask, % "x" ix " y" iy " w" innerSize " h" innerSize
    GuiControl, AltTab:Show, InnerMask
    GuiControl, AltTab:MoveDraw, InnerMask

    GuiControl, AltTab:, TitleText, % oTitle[vIndex]
return

; ---------------------------------- Mouse Hover Tracking ----------------------------------
CheckHover:
    if (!guiActive)
        return
    MouseGetPos, , , win, ctrl
    if (win != hWndGUI || ctrl = "")
        return
    ControlGet, ctrlHwnd, Hwnd,, %ctrl%, ahk_id %win%
    if (!ctrlHwnd)
        return
    Loop % vCount {
        if (ctrlHwnd = IconCtrlHwnd[A_Index]) {
            if (A_Index != vIndex) {
                vIndex := A_Index
                Gosub, UpdateHighlight
            }
            break
        }
    }
return

; ---------------------------------- Mouse Click Handler ----------------------------------
OnIconClick:
    idx := SubStr(A_GuiControl, 2)  ; "I#" → #
    if (idx >= 1 && idx <= vCount) {
        vIndex := idx
        WinActivate, % "ahk_id " oHWnd[vIndex]
        SetTimer, CheckHover, Off
        Gui, AltTab:Hide
        guiActive := false
        persistentAltTab := false
        ForceModifierReset()
    }
return

; ---------------------------------- Icon helper ----------------------------------
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"))
         || (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",0, "Ptr",0, "Ptr"))
         || (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",2, "Ptr",0, "Ptr"))
         || (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-14, "UPtr"))
         || (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-34, "UPtr"))
         || (hIcon := DllCall("user32\LoadIcon", "Ptr",0, "Ptr",32512, "Ptr"))
            return hIcon
    } else {
        if (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",0, "Ptr",0, "Ptr"))
         || (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",2, "Ptr",0, "Ptr"))
         || (hIcon := DllCall("user32\SendMessage", "Ptr",hWnd, "UInt",0x7F, "UPtr",1, "Ptr",0, "Ptr"))
         || (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-34, "UPtr"))
         || (hIcon := DllCall("user32\GetClassLong" vSfx, "Ptr",hWnd, "Int",-14, "UPtr"))
         || (hIcon := DllCall("user32\LoadIcon", "Ptr",0, "Ptr",32512, "Ptr"))
            return hIcon
    }
    return 0
}

; ---------------------------------- Alt+Tab membership ----------------------------------
JEE_WinHasAltTabIcon(hWnd) {
    if !(DllCall("user32\GetDesktopWindow", "Ptr") = DllCall("user32\GetAncestor", "Ptr",hWnd, "UInt",1, "Ptr"))
        return 0
    WinGet, vWinStyle, Style, % "ahk_id " hWnd
    if !vWinStyle || !(vWinStyle & 0x10000000) || (vWinStyle & 0x8000000)
        return 0
    WinGet, vWinExStyle, ExStyle, % "ahk_id " hWnd
    if (vWinExStyle & 0x40000)
        return 1
    if (vWinExStyle & 0x80) || (vWinExStyle & 0x8000000)
        return 0
    return 1
}

; ---------------------------------- Custom Icon Resolver ----------------------------------
GetCustomIconPath(vClass, title, proc) {
    global CustomIcons
    key1 := vClass ":" title
    key2 := "#TITLE:" . title
    key3 := "#CLASS:" . vClass
    key4 := "#PROC:"  . proc

    if (CustomIcons.HasKey(key1))
        return CustomIcons[key1]
    if (CustomIcons.HasKey(key2))
        return CustomIcons[key2]
    if (CustomIcons.HasKey(key3))
        return CustomIcons[key3]
    if (CustomIcons.HasKey(key4))
        return CustomIcons[key4]
    return ""
}

; ---------------------------------- Dark or Light GUI ----------------------------------
ToggleThemeMode:
    ThemeMode := (ThemeMode = "Light") ? "Dark" : "Light"
    SaveThemeMode()
    TrayTip, Theme Changed, Switched to %ThemeMode% Mode, 10
    Reload
return

; ---------------------------------- Accent Color GUI ----------------------------------
SetAccentColor() {
    RegRead, accentColorHex, HKCU\Software\Microsoft\Windows\DWM, ColorizationColor
    if (ErrorLevel) {
        MsgBox, Failed to read accent color from registry.
        return
    }

    ; Convert DWORD (ARGB) to RGB hex (ignore alpha)
    rgb := accentColorHex & 0xFFFFFF
    r := (rgb >> 16) & 0xFF
    g := (rgb >> 8) & 0xFF
    b := rgb & 0xFF
    rgbHex := Format("0x{:02X}{:02X}{:02X}", r, g, b)

    global PanelColor := rgbHex
    global ThemeMode := "Accent"

    ; Calculate perceived brightness (using luminance formula)
    brightness := 0.299 * r + 0.587 * g + 0.114 * b

    if (brightness > 160) {
        global TitleColor := "BLACK"
        global HighLightColor := "0x004DFF"  ; or a darker accent variant
    } else {
        global TitleColor := "WHITE"
        global HighLightColor := "0x80FFFF"  ; or a lighter accent variant
    }

    SaveThemeMode()
    TrayTip, Theme Changed, Using System Accent Color, 10
    Reload
}

; ---------------------------------- Rounded or Squared GUI ----------------------------------
ToggleRoundedCorners:
    global RoundedCorners := !RoundedCorners
    SaveThemeMode()            ; <-- Add this line
    SaveRoundedCorners()
    TrayTip, Corner Style Changed, % RoundedCorners ? "Rounded Corners Enabled" : "Squared Corners Enabled", 10
    Reload
return

; ---------------------------------- Modifier reset helper ----------------------------------
ForceModifierReset() {
    SendInput {Blind}{Alt Up}{Shift Up}{Ctrl Up}{Tab Up}
}

; ------------------------- Theme Handlers -------------------------
SetLightMode:
    ThemeMode := "Light"
    SaveThemeMode()
    Reload
return

SetDarkMode:
    ThemeMode := "Dark"
    SaveThemeMode()
    Reload
return

; ------------------------- Save -------------------------
SaveRoundedCorners() {
    IniWrite, % RoundedCorners ? "1" : "0", %A_ScriptDir%\theme.ini, Settings, RoundedCorners
}

SaveThemeMode() {
    IniWrite, %ThemeMode%, %A_ScriptDir%\theme.ini, Settings, ThemeMode
}

; ------------------------- Exit -------------------------
ExitScript:
    ExitApp
return
 
Link to comment
Share on other sites

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • AD
  • Recent Status Updates

    No Recent Status Updates
  • Most Solved

    Nothing has been solved this week.

×
×
  • Create New...