你如何在 AutoHotkey 中获取当前的键盘布局(语言设置)

How do you get the current keyboard layout (language setting) in AutoHotkey

我希望能够让我的脚本对当前的键盘布局敏感。像

#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

Windows 允许为每个 window 独立设置自定义语言。如果你不介意,你可以使用主动window。您可以使用此脚本检索 Language ID(给出了一些示例):

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%)

. According to MSDN返回的值实际上是两个:

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.

所以可以有很多组合,你需要的是第二个值。所以我想到了这个:

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 }
}