Reputation: 1676
I would like to have the possibility to let my script be sensitive to the current keyboard-layout. Something like
#If %keyboardLang% == en-US
a::
MsgBox, I pressed a on an english keyboard
return
#If %keyboardLang% == de-US
a::
MsgBox, I pressed a on an german keyboard
return
Upvotes: 1
Views: 1801
Reputation: 3192
To those whom it may concern, AHK2.x version:
GetCurrentKeyboardLayout() {
hwnd := DllCall("GetForegroundWindow")
if hwnd == 0
return 0
threadID := DllCall("GetWindowThreadProcessId", "UInt", hwnd, "UInt", 0)
return DllCall("GetKeyboardLayout", "UInt", threadID, "UInt")
}
Upvotes: 2
Reputation: 98
@Cadoiz pointed you in the right direction. According to MSDN the value returned is in fact two:
The name of the input locale identifier to load. This name is a string composed of the hexadecimal value of the Language Identifier (low word) and a device identifier (high word). For example, U.S. English has a language identifier of 0x0409, so the primary U.S. English layout is named "00000409". Variants of U.S. English layout -- (such as the Dvorak layout) are named "00010409", "00020409", and so on.
So there can be lots of combinations, what you need is the second value. So I came up with this:
F1::
MsgBox % "Keyboard layout: " GetLayout(Language := "") "`n"
. "Keyboard language identifier: " Language
return
#if GetLayout(Language := "") = "gr"
a::MsgBox 0x40, Layout, % "Current layout: " Language
#if GetLayout(Language := "") = "us"
a::MsgBox 0x40, Layout, % "Current layout: " Language
#if
GetLayout(ByRef Language := "")
{
hWnd := WinExist("A")
ThreadID := DllCall("GetWindowThreadProcessId", "Ptr",hWnd, "Ptr",0)
KLID := DllCall("GetKeyboardLayout", "Ptr",ThreadID, "Ptr")
KLID := Format("0x{:x}", KLID)
Lang := "0x" A_Language
Locale := KLID & Lang
Info := KeyboardInfo()
return Info.Layout[Locale], Language := Info.Language[Locale]
}
KeyboardInfo()
{
static Out := {}
if Out.Count()
return Out
Layout := {}
loop reg, HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes
{
RegRead Data
Code := "0x" A_LoopRegName
Layout[Code + 0] := Data
}
Language := {}
loop reg, HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts, KVR
{
RegRead Data
if ErrorLevel
Name := "0x" A_LoopRegName
else if (A_LoopRegName = "Layout Text")
Language[Name + 0] := Data
}
return Out := { "Layout":Layout, "Language":Language }
}
Upvotes: 3
Reputation: 1676
Windows allows custom language settings independently for each window. If you don't care, you can just use the active window. You can retrieve a Language ID with this script (some examples given):
SetFormat, Integer, H
WinGet, WinID,, A ;get the active Window
ThreadID:=DllCall("GetWindowThreadProcessId", "UInt", WinID, "UInt", 0)
InputLocaleID:=DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
if (InputLocaleID == 0x4070407)
languageName = german
else if (InputLocaleID == 0xF0010409)
languageName = US international
else if (InputLocaleID == 0x4090409 )
languageName = US english
MsgBox, The language of the active window is %languageName%. (code: %InputLocaleID%)
Upvotes: 1