Created
February 17, 2025 06:46
-
-
Save joseph-sch/830b0c3f8e94b43414ea538195461724 to your computer and use it in GitHub Desktop.
For multi-language Windows users, make the keyboard choice prominent when it changes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires AutoHotkey v2.0 | |
#SingleInstance Force | |
global popup, langText, guiCreated := false, prevLangID := 0 | |
; Check the keyboard layout every 200ms | |
SetTimer(CheckKeyboardLayout, 200) | |
CheckKeyboardLayout() { | |
global popup, langText, guiCreated, prevLangID | |
; Get focused window handle | |
hwndFocus := GetFocusedWindowHandle() | |
if (!hwndFocus) { | |
ToolTip("No window in focus") | |
SetTimer(() => ToolTip(""), -1000) | |
return | |
} | |
; Retrieve the language ID of the keyboard layout for the focused window | |
langID := GetKeyboardLangID(hwndFocus) | |
; Exit if the language hasn't changed | |
if (langID = prevLangID) | |
return | |
; Store the new language ID | |
prevLangID := langID | |
; Get the middle of the active window | |
try { | |
WinGetPos(&x, &y, &w, &h, "A") | |
x := x + w // 2 | |
y := y + h // 2 | |
} catch as e { | |
x := 0 | |
y := 0 | |
} | |
; If it doesn't exist, create the GUI object | |
if (!guiCreated) { | |
popup := Gui("+AlwaysOnTop -Caption +ToolWindow") | |
popup.SetFont("s32 Bold cFFFFFF", "Arial") | |
langText := popup.Add("Text", "Center", LangIDToLabel(langID).label) | |
guiCreated := true | |
} | |
; Set the language text and background color | |
langText.Text := LangIDToLabel(langID).label | |
popup.BackColor := LangIDToLabel(langID).color | |
; Show the popup at the chosen position | |
popup.Show("x" x " y" y " NoActivate") | |
; Hide the popup after 1.5 second | |
SetTimer(HideLayoutGui, -1500) | |
} | |
GetKeyboardLangID(hWnd) { | |
; Retrieve the thread ID for the window | |
threadID := DllCall("GetWindowThreadProcessId", "Ptr", hWnd, "Ptr", 0, "UInt") | |
; Retrieve the current keyboard layout for that thread | |
currentLayout := DllCall("GetKeyboardLayout", "UInt", threadID, "Ptr") | |
; Extract the language ID (low word) | |
langID := currentLayout & 0xFFFF | |
; Return the language ID | |
return langID | |
} | |
LangIDToLabel(langID) { | |
; Determine language code and background color | |
if (langID = 0x0409) { | |
; English (US International) | |
label := "ENG" | |
color := "797300" | |
} else if (langID = 0x040C) { | |
; French (US International) | |
label := "FRA" | |
color := "090fc7" | |
} else if (langID = 0x040D) { | |
; Hebrew (Standard) | |
label := "HEB" | |
color := "af0101" | |
} else { | |
label := Format("0x{:04X}", langID) | |
color := "FFFFFF" ; White fallback | |
} | |
; Return an object with both lang and color | |
return { label: label, color: color } | |
} | |
HideLayoutGui() { | |
global popup | |
popup.Hide() | |
} | |
GetFocusedWindowHandle() { | |
info := Buffer(72, 0) | |
NumPut("UInt", 72, info) ; Set the cbSize member to 72 | |
res := DllCall("GetGUIThreadInfo", "UInt", 0, "Ptr", info.Ptr) | |
if (!res) | |
return 0 | |
return NumGet(info, 16, "Ptr") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ChatGPT's o3-mini's comments: