Jump to content

How to detect Qwerty vs Dvorak layout?


Recommended Posts

Hi guys,

I've seen the @kblayout macro, but the information I'm after is the keyboard layout (aka "Input Method") so I can detect if I'm using "US Keyboard" or "United States-Dvorak Keyboard" rather than 00000c09 or 00000409 which relate to languages such as EN AU or EN US for example.

For example I have 1 language set up (English Australia) in my regional settings, but then under the language I have "US Keyboard" and "United States-Dvorak Keyboard" setup, so that when I press WIN+SPACE I can toggle between them.

Effectively I want a way of determining if I'm running qwerty or dvorak.

Thanks guys!!

Link to comment
Share on other sites

I think @kblayout macro calls GetKeyboardLayout API, but it retrieves only low order byte, so it gets only the language identifier, you need the device identifier (also known as device handle or physical layout) too that's contained in high order bytes.

 

EDIT: On second thought, @kblayout macro calls GetKeyboardLayoutName function, which retrieves by default only language ID.

Edited by j0kky
Link to comment
Share on other sites

Don't you like GetKeyboardLayout?

#include <WinAPI.au3>

HotKeySet("{SPACE}", _GetKeyboardLayout)
HotKeySet("{ESC}", _Exit)

While 1
    Sleep(100)
WEnd

Func _GetKeyboardLayout()
    Local $aRet = DllCall("user32.dll", "HANDLE", "GetKeyboardLayout", "DWORD", 0)
    If @error Then
        ConsoleWrite("ERROR!" & @CRLF)
        Return
    EndIf
    ConsoleWrite("Language Identifier: " & Hex(_WinAPI_LoWord($aRet[0]), 4) & @CRLF & _
        "Device Identifier: " & Hex(_WinAPI_HiWord($aRet[0]), 4) & @CRLF & @CRLF)
EndFunc

Func _Exit()
    Exit
EndFunc

 

Edited by j0kky
Link to comment
Share on other sites

That's really strange... Try this switching between the two keyboard setup without closing the application (and mantaining it on the top level). 

#include <WinAPI.au3>

Global Const $WM_INPUTLANGCHANGE = 0x0051
$hGUI = GUICreate("My GUI")
GUIRegisterMsg($WM_INPUTLANGCHANGE, "_WM_INPUTLANGCHANGE")
GUISetState(@SW_SHOW)
HotKeySet("{ESC}", _Exit)
WinActivate($hGUI)

While 1
    Sleep(100)
WEnd

Func _WM_INPUTLANGCHANGE($hWnd, $iMsg, $wParam, $lParam)
    Local $aRet = DllCall("user32.dll", "HANDLE", "GetKeyboardLayout", "DWORD", 0)
    If @error Then
        ConsoleWrite("ERROR!" & @CRLF)
        Return
    EndIf
    ConsoleWrite("Handle: " & $aRet[0]  & @CRLF & _
        "Language Identifier: " & Hex(_WinAPI_LoWord($aRet[0]), 4) & @CRLF & _
        "Device Identifier: " & Hex(_WinAPI_HiWord($aRet[0]), 4) & @CRLF & _
        "wParam: " & $wParam & @CRLF & _
        "lParam: " & $lParam & @CRLF & @CRLF)
    Return 'GUI_RUNDEFMSG'
EndFunc

Func _Exit()
    Exit
EndFunc

Then post here full console output.

Edited by j0kky
Link to comment
Share on other sites

  • 2 weeks later...

Sorry about the delay!

Here's the output from the script, changing to EN-AU Dvorak first, then changing back to EN-AU Qwerty.

Quote

Handle: 0xF0020C09
Language Identifier: 0C09
Device Identifier: F002
wParam: 0x00000000
lParam: 0xF0020C09

Handle: 0x04090C09
Language Identifier: 0C09
Device Identifier: 0409
wParam: 0x00000000
lParam: 0x04090C09

Looks like the device identifier has picked it up while running the gui! I tried a truncated version of your script without the gui in a loop and it doesn't return the same result.

Edited by WoodGrain
Link to comment
Share on other sites

  • 3 weeks later...

What did you do to remove the GUI? You shouldn't need it for the code to run, you can start it and have it run in the tray with a hotkey or something.

EDIT: Upon further inspection it seems we need GuiRegisterMsg for this to work, so alternatively you could just try to make the GUI invisible in the background. I don't know if there is a non-GUI alternative to this function.

Edited by anthonyjr2

UHJvZmVzc2lvbmFsIENvbXB1dGVyZXI=

Link to comment
Share on other sites

  • 2 weeks later...

Hehe, an invisible gui. I guess if there's not another option it's the best available way.

I've really done nothing with the gui before, does this create much overhead in the script?
I'm wanting to check the state of the keyboard layout every second.

Thanks.

Link to comment
Share on other sites

  • 3 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...