Detect keyboard layout code needs fix for v2-a124 Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
phaleth
Posts: 38
Joined: 13 Apr 2015, 03:49

Detect keyboard layout code needs fix for v2-a124

21 Feb 2021, 11:33

Bellow is a code for keyboard layout detection. The code works perfectly fine on ahk v2-a110. On ahk v2-a124 there is something wrong with the NumPut() function call and the interpreter displays an error. Any idea how to fix the code?

I've noticed the docs for NumPut() have changed, but in a way that I cannot understand. I've tried to swap the args of the function call around, which did not help fixing the code.

Code: Select all

MsgBox(checkWindowKBD())

checkWindowKBD() {
; Function by Drugwash
    threadID := GetFocusedThread(hwnd := WinExist("A"))
    hkl := DllCall("user32\GetKeyboardLayout", "UInt", threadID)        ; 0 for current thread
  ; hkl: 1=next, 0=previous | flags: 0x100=KLF_SETFORPROCESS
    If !DllCall("user32\ActivateKeyboardLayout", "Ptr", hkl, "UInt", 0x100)
    {
        ;Format("Integer", H)
        l := SubStr(hkl & 0xFFFF, 3)
        klid := SubStr("00000000" l, -8)
        ;Format("Integer", D)
        ; flags: 0x100=KLF_SETFORPROCESS 0x1=KLF_ACTIVATE 0x2=KLF_SUBSTITUTE_OK
        DllCall("user32\LoadKeyboardLayoutW", "Str", klid, "UInt", 0x103)
    }
    DllCall("user32\GetKeyboardLayoutNameW", "Str", klid:="00000000")
    ; ToolTip("hwndA=" hwnd " -- hkl=" hkl " -- klid=" klid)
    Return klid
}

GetFocusedThread(hwnd := 0) {
; Function by Drugwash
    If !hwnd
       Return 0  ; current thread
    tid := DllCall("user32\GetWindowThreadProcessId", "Ptr", hwnd, "Ptr", 0)
    VarSetStrCapacity(GTI, sz := 24+6*A_PtrSize)      ; GUITHREADINFO struct
    ; NumPut(Number, VarOrAddress , Offset := 0, Type := "UPtr")
    NumPut(sz, GTI, 0, "UInt")  ; cbSize
    ; NumPut(Type, Number, Target , Offset)
    ;NumPut("UInt", sz, GTI, 0) ; cbSize
    If DllCall("user32\GetGUIThreadInfo", "UInt", tid, "Ptr", GTI)
       If hF := NumGet(GTI, 8+A_PtrSize, "Ptr")
          Return DllCall("user32\GetWindowThreadProcessId", "Ptr", hF, "Ptr", 0)
    Return 0  ; current thread (actually it's an error but we couldn't care less)
}
image.png
image.png (119.28 KiB) Viewed 838 times
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Detect keyboard layout code needs fix for v2-a124

21 Feb 2021, 12:13

u need to stop using VatSetXXX and replace them with BufferAlloc.
NumPut calls need to obey the proper signature
phaleth
Posts: 38
Joined: 13 Apr 2015, 03:49

Re: Detect keyboard layout code needs fix for v2-a124

22 Feb 2021, 02:22

swagfag wrote:
21 Feb 2021, 12:13
u need to stop using VatSetXXX and replace them with BufferAlloc.
NumPut calls need to obey the proper signature
Could you please provide more details? I don't follow any of that.
phaleth
Posts: 38
Joined: 13 Apr 2015, 03:49

Re: Detect keyboard layout code needs fix for v2-a124  Topic is solved

22 Feb 2021, 15:03

After giving the problem a closer look I was able to fix the code for v2-a124.

Code: Select all

MsgBox(checkWindowKBD())

checkWindowKBD() {
    threadID := GetFocusedThread(hwnd := WinExist("A"))
    hkl := DllCall("user32\GetKeyboardLayout", "UInt", threadID)        ; 0 for current thread
  ; hkl: 1=next, 0=previous | flags: 0x100=KLF_SETFORPROCESS
    If !DllCall("user32\ActivateKeyboardLayout", "Ptr", hkl, "UInt", 0x100)
    {
        ;Format("Integer", H)
        l := SubStr(hkl & 0xFFFF, 3)
        klid := SubStr("00000000" l, -8)
        ;Format("Integer", D)
        ; flags: 0x100=KLF_SETFORPROCESS 0x1=KLF_ACTIVATE 0x2=KLF_SUBSTITUTE_OK
        DllCall("user32\LoadKeyboardLayoutW", "Str", klid, "UInt", 0x103)
    }
    DllCall("user32\GetKeyboardLayoutNameW", "Str", klid:="00000000")
    ; ToolTip("hwndA=" hwnd " -- hkl=" hkl " -- klid=" klid)
    Return klid
} ; by Drugwash

GetFocusedThread(hwnd := 0) {
    If !hwnd
       Return 0  ; current thread
    tid := DllCall("user32\GetWindowThreadProcessId", "Ptr", hwnd, "Ptr", 0)
    ; VarSetStrCapacity(TargetVar [, RequestedCapacity])
    ; VarSetStrCapacity(GTI, sz := 24+6*A_PtrSize)  ; GUITHREADINFO struct
    ; Buffer := BufferAlloc(ByteCount [, FillByte])
    GTI := BufferAlloc(sz := 24+6*A_PtrSize)  ; GUITHREADINFO struct
    ; NumPut(Number, VarOrAddress , Offset := 0, Type := "UPtr")
    ; NumPut(sz, GTI, 0, "UInt")  ; cbSize
    ; NumPut(Type, Number, Target , Offset)
    NumPut("UInt", sz, GTI, 0) ; cbSize
    If DllCall("user32\GetGUIThreadInfo", "UInt", tid, "Ptr", GTI)
       If hF := NumGet(GTI, 8+A_PtrSize, "Ptr")
          Return DllCall("user32\GetWindowThreadProcessId", "Ptr", hF, "Ptr", 0)
    Return 0  ; current thread (actually it's an error but we couldn't care less)
} ; by Drugwash

Thank you for the pointers, @swagfag.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: kunkel321, shipaddicted, Spikea and 60 guests