Skip to content

Instantly share code, notes, and snippets.

@mariusrueve
Last active February 15, 2025 18:28
Show Gist options
  • Save mariusrueve/c6b1af96c1d5b5792c150e52c8500288 to your computer and use it in GitHub Desktop.
Save mariusrueve/c6b1af96c1d5b5792c150e52c8500288 to your computer and use it in GitHub Desktop.
AHK Active Window Rounded Border (Win11 24H2)
; ================================
; Active Window Rounded Border Overlay
; For Windows 11 (24H2)
; Runs continuously in the background.
; Adjust the border color, thickness, and corner roundness below.
; ================================
#NoEnv
#SingleInstance, Force
#Persistent
SetBatchLines, -1
SendMode, Input
SetWorkingDir, %A_ScriptDir%
; ------------- User Settings -------------
borderColor := 0x357EC7 ; Hex color (0xRRGGBB)
borderThickness:= 4 ; Border thickness in pixels
cornerRadius := 12 ; Corner roundness in pixels
updateInterval := 20 ; How often (ms) to check/update active window
; ------------- End Settings -------------
; --- Create one overlay GUI that will be re‑shaped to form a hollow border ---
Gui, Overlay: +AlwaysOnTop +ToolWindow -Caption +E0x20 ; +E0x20 makes it click‑through.
; Set the background color of the overlay (it will only be visible in its “region”)
; Convert the numeric color (0xRRGGBB) to a 6‑digit hex string (without “0x”)
bgColor := Format("{:06X}", borderColor & 0xFFFFFF)
Gui, Overlay: Color, %bgColor%
Gui, Overlay: Show, NoActivate, ActiveWindowBorder
hOverlay := WinExist("ActiveWindowBorder")
; Add layered style so that SetWindowRgn is applied smoothly.
WinSet, ExStyle, +0x80000, ahk_id %hOverlay%
; Global variables to track the last active window’s position & size.
global prevHWND := "", prevAx, prevAy, prevAw, prevAh
; Set up a timer to update the overlay border.
SetTimer, UpdateBorder, %updateInterval%
Return
; -------------------------------
; UpdateBorder: Positions/resizes and re‑shapes the overlay border
; -------------------------------
UpdateBorder:
; Get the currently active window.
WinGet, activeHWND, ID, A
; (Ignore the overlay itself if it somehow becomes active)
if (activeHWND = hOverlay)
{
WinGet, activeHWND, ID, A
}
; If no active window found or if the window is minimized, hide the overlay.
if (!activeHWND) {
Gui, Overlay: Hide
Return
}
WinGet, style, Style, ahk_id %activeHWND%
if (style & 0x20000000) { ; WS_MINIMIZE flag
Gui, Overlay: Hide
Return
}
; --- Get the window's true bounds using DWM (works better for Windows 11) ---
VarSetCapacity(rect, 16, 0)
if (DllCall("dwmapi\DwmGetWindowAttribute", "ptr", activeHWND, "uint", 9, "ptr", &rect, "uint", 16) = 0)
{
ax := NumGet(rect, 0, "int")
ay := NumGet(rect, 4, "int")
right := NumGet(rect, 8, "int")
bottom := NumGet(rect, 12, "int")
aw := right - ax
ah := bottom - ay
}
else {
; Fallback in case DWM fails.
WinGetPos, ax, ay, aw, ah, ahk_id %activeHWND%
}
; Only update if something changed.
if (activeHWND = prevHWND && ax = prevAx && ay = prevAy && aw = prevAw && ah = prevAh)
Return
prevHWND := activeHWND, prevAx := ax, prevAy := ay, prevAw := aw, prevAh := ah
; Calculate overlay position and size.
; The overlay is expanded by borderThickness on all sides so that its inner edge aligns
; exactly with the active window’s border.
ox := ax - borderThickness
oy := ay - borderThickness
ow := aw + (2 * borderThickness)
oh := ah + (2 * borderThickness)
; (Re)position the overlay window.
Gui, Overlay: Show, x%ox% y%oy% w%ow% h%oh% NoActivate
; ----- Build a hollow (donut‑shaped) region with rounded corners -----
; Outer region: a rounded rectangle covering the full overlay.
hRgnOuter := DllCall("CreateRoundRectRgn", "Int", 0, "Int", 0, "Int", ow, "Int", oh, "Int", cornerRadius*2, "Int", cornerRadius*2, "Ptr")
; Inner region: same shape, inset by borderThickness.
innerCorner := (cornerRadius > borderThickness) ? (cornerRadius - borderThickness) : 0
hRgnInner := DllCall("CreateRoundRectRgn", "Int", borderThickness, "Int", borderThickness, "Int", ow - borderThickness, "Int", oh - borderThickness, "Int", innerCorner*2, "Int", innerCorner*2, "Ptr")
; Create a region for the border by subtracting the inner region from the outer.
; First, create an empty region.
hRgnBorder := DllCall("CreateRectRgn", "Int", 0, "Int", 0, "Int", 0, "Int", 0, "Ptr")
; RGN_DIFF = 4: hRgnBorder = hRgnOuter - hRgnInner.
DllCall("CombineRgn", "Ptr", hRgnBorder, "Ptr", hRgnOuter, "Ptr", hRgnInner, "Int", 4)
; Apply the computed region to the overlay window.
; (After calling SetWindowRgn, the system owns hRgnBorder, so DO NOT free it.)
DllCall("SetWindowRgn", "Ptr", hOverlay, "Ptr", hRgnBorder, "Int", True)
; Clean up the temporary region handles.
DllCall("DeleteObject", "Ptr", hRgnOuter)
DllCall("DeleteObject", "Ptr", hRgnInner)
Return
@mariusrueve
Copy link
Author

This is what it looks like with a different border color

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment