Adele Posted August 18, 2015 Share Posted August 18, 2015 (edited) I want to detect when the user has changed the keyboard layout on command line. I've tried _WinAPI_GetKeyboardLayout() function. It works wonderful with other programs but doesn't work on command line. I change the keyboard layout but the function returns always initial value.I've prepared a script to detect changes. You could see the problem with through testing.#include <WinAPISys.au3> #RequireAdmin Global $hWnd, $bKey Opt("TrayAutoPause", 0) Run("cmd.exe") $hWnd = WinWait("[CLASS:ConsoleWindowClass]") OnAutoItExitRegister("closing") While 1 Sleep(100) $bNewKey = _WinAPI_GetKeyboardLayout($hWnd) ConsoleWrite("Current keyboard layout: " & $bNewKey & @CRLF) If $bKey AND $bNewKey AND $bNewKey <> $bKey Then MsgBox(64, "Warning", "The keyboard layout changes has been detected." & @CRLF & "The previous keyboard layout: "& $bKey & @CRLF & "The new keyboard layout: " & $bNewKey) Exit ElseIf Not $bNewKey Then Exit EndIf $bKey = $bNewKey WEnd Func closing() WinKill($hWnd) EndFuncIf you test it with Notepad, there isn't a problem.#include <WinAPISys.au3> #RequireAdmin Global $hWnd, $bKey Opt("TrayAutoPause", 0) Run("notepad.exe") $hWnd = WinWait("[CLASS:Notepad]") OnAutoItExitRegister("closing") While 1 Sleep(100) $bNewKey = _WinAPI_GetKeyboardLayout($hWnd) ConsoleWrite("Current keyboard layout: " & $bNewKey & @CRLF) If $bKey AND $bNewKey AND $bNewKey <> $bKey Then MsgBox(64, "Warning", "The keyboard layout changes has been detected." & @CRLF & "The previous keyboard layout: "& $bKey & @CRLF & "The new keyboard layout: " & $bNewKey) Exit ElseIf Not $bNewKey Then Exit EndIf $bKey = $bNewKey WEnd Func closing() WinKill($hWnd) EndFuncThank you in advance. Edited August 19, 2015 by Adele Link to comment Share on other sites More sharing options...
Jfish Posted August 19, 2015 Share Posted August 19, 2015 (edited) I read your post a couple of times. I think you are saying that it does not work without a window for a program to detect the changes. If so, that is in line with the explanation in the help file: "Retrieves the active input locale identifier for the specified window".I think you can do it from the command line as discussed here: http://superuser.com/questions/841236/how-to-know-which-keyboard-layout-is-currently-active-using-cmd-in-windows-7-32b Edited August 19, 2015 by Jfish Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 20, 2015 Author Share Posted August 20, 2015 Sorry for my English.In summary; _WinAPI_GetKeyboardLayout() can get specific window's keyboard layout. It works with other programs but doesn't get on command prompt window. It always returns the same value. I read your post a couple of times. I think you are saying that it does not work without a window for a program to detect the changes. If so, that is in line with the explanation in the help file: "Retrieves the active input locale identifier for the specified window".I think you can do it from the command line as discussed here: http://superuser.com/questions/841236/how-to-know-which-keyboard-layout-is-currently-active-using-cmd-in-windows-7-32bUnfortunately, I don't mean this. I want to get command prompt window's keyboard layout via Autoit. Thank you for reply. Link to comment Share on other sites More sharing options...
guinness Posted August 20, 2015 Share Posted August 20, 2015 You're Adele, English is your native language! Adele 1 UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
Jfish Posted August 20, 2015 Share Posted August 20, 2015 (edited) LOL. (I heard the hipsters now say "haha"). Yes, I love your music. That said, do you mean something like this?run('cmd.exe') sleep(2000) send('reg query "HKEY_CURRENT_USER\Keyboard Layout\Preload"') send("{enter}")You can also use shellexecute and run but the command line window won't stay open. Edited August 20, 2015 by Jfish Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 21, 2015 Author Share Posted August 21, 2015 (edited) @Jfish Sorry. It shows keyboard list on the system. I want to get selected keyboard layout on a window. Like I gave example above.#include <WinAPISys.au3> #RequireAdmin Global $hWnd, $bKey Opt("TrayAutoPause", 0) Run("notepad.exe") $hWnd = WinWait("[CLASS:Notepad]") OnAutoItExitRegister("closing") While 1 Sleep(100) $bNewKey = _WinAPI_GetKeyboardLayout($hWnd) ConsoleWrite("Current keyboard layout: " & $bNewKey & @CRLF) If $bKey AND $bNewKey AND $bNewKey <> $bKey Then MsgBox(64, "Warning", "The keyboard layout changes has been detected." & @CRLF & "The previous keyboard layout: "& $bKey & @CRLF & "The new keyboard layout: " & $bNewKey) Exit ElseIf Not $bNewKey Then Exit EndIf $bKey = $bNewKey WEnd Func closing() WinKill($hWnd) EndFuncThis code detects when the user has changed the keyboard layout while Notepad is running. I use _WinAPI_GetKeyboardLayout() function here. The problem is that; this function doesn't work on command prompt window. Edited August 21, 2015 by Adele Link to comment Share on other sites More sharing options...
Jfish Posted August 21, 2015 Share Posted August 21, 2015 Still confused on my side . Are you trying to detect the keyboard layout for the window with the title "Command Prompt" or are you trying to run your program from the command prompt to find the keyboard layout of another program/window? Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 21, 2015 Author Share Posted August 21, 2015 Are you trying to detect the keyboard layout for the window with the title "Command Prompt"Exactly this. Link to comment Share on other sites More sharing options...
Jfish Posted August 21, 2015 Share Posted August 21, 2015 (edited) Okay, how about this?#include <WinAPISys.au3> Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase $windowTitle="Command Prompt" $windowHandle=WinActivate($windowTitle) $keyboard=_WinAPI_GetKeyboardLayout ($windowHandle) MsgBox(0,"Keyboard",$keyboard) Edited August 21, 2015 by Jfish Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 21, 2015 Author Share Posted August 21, 2015 (edited) Okay, how about this?#include <WinAPISys.au3> Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase $windowTitle="Command Prompt" $windowHandle=WinActivate($windowTitle) $keyboard=_WinAPI_GetKeyboardLayout ($windowHandle) MsgBox(0,"Keyboard",$keyboard) There isn't a problem this section. When you changed the keyboard layout, it still returns the same value. I've worked to tell with screenshots:The function always returns the same value on Command Prompt. The problem is here.......................But the function can detect uptodate and true value on other programs like Notepad. Edited August 22, 2015 by Adele Link to comment Share on other sites More sharing options...
Jfish Posted August 22, 2015 Share Posted August 22, 2015 Okay, this is untested - because I am not sure how you change the keyboard layout for the Command Prompt window. However, I did notice a problem with the _WinAPI_GetKeyboardLayout function. It seems to work intermittently and was having issues inside a loop. I am not sure what I did but my code above stopped working. I decided to switch functions and use the keyboard list. I assume the first entry is the current keyboard (that may or may not be true as I only have 1). Again, the part that detects the change is untested but let me know if something like this works for you ...#include <WinAPISys.au3> #include <Array.au3> Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase Global $currentKeyboard=_getKeyBoard() ;ConsoleWrite(@CRLF&$currentKeyboard&@CRLF) Global $newKeyboard=$currentKeyboard ;ConsoleWrite(@CRLF&$newKeyboard&@CRLF) func _getKeyBoard() $windowTitle="Command Prompt" $windowHandle=WinActivate($windowTitle) local $keyboardList=_WinAPI_GetKeyboardLayoutList ( ) return $keyboardList[1] EndFunc while 1 sleep(1000) $currentKeyboard=_getKeyBoard() If $currentKeyboard <> $newKeyboard Then MsgBox(0,"Change Detected","New Keyboard is: "&$currentKeyboard) $newKeyboard=$currentKeyboard Else ConsoleWrite(@CRLF&$currentKeyboard&@CRLF) EndIF WEnd Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 22, 2015 Author Share Posted August 22, 2015 @Jfish Sorry, it returns keyboard list as ordering. It doesn't give the selected keyboard layout. Link to comment Share on other sites More sharing options...
Jfish Posted August 22, 2015 Share Posted August 22, 2015 Yes, it returns an array. I am using the first element in the array. Is that not the selected keyboard? Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Gianni Posted August 23, 2015 Share Posted August 23, 2015 (edited) maybe a workaround could be to be able to read the status of the checked language in the tray menu or at least the text of the associated tooltip....it seems that the Handle of the "language selector" control is this [CLASS:CiceroUIWndFrame] but I have not idea on how to grab his status or text.once we can get the text of that control, we could activate the cmd window and check his active language by reading the status of the "language selector" control. (indeed the status of this control changes any time you select a new window, showing his associated language.)EDIT:to try this behaviour do this:1) open 2 cmd windows2) activate one of those cmd and change his keyb language on the "language selector" in the tray bar3) then alternately click on both cmd windows ant see the "text" changing on the keyb language tray controlEDIT 2:other weirdnessif you type this 2 commands within a cmd promt:chcpormode con cpthe result is the active table codebut the result is always the same even when you change the keyboard language on the "language selector" tollbar control or by the chcp or the mode con cp commands... Edited August 23, 2015 by Chimp Adele 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Jfish Posted August 23, 2015 Share Posted August 23, 2015 (edited) I have been researching this a bit. This may be a problem with the console vs. other windows. I did not verify the way the user32.dll works - but this may explain it:GetKeyboardLayout works with applications running in the WINDOWS subsystem (it's a user32.dll export). Command line applications run in the CONSOLE subsystem.Cite: http://stackoverflow.com/questions/29217501/getkeyboardlayout-doesnt-work-properly-in-some-casesI can detect the changes this way ... NOTE: not sure why I can't get it to work with the standard function - mine is basically the same except the way I open the DLL call (should not make a difference).Func _WinAPI_GetKeyboardLayout2($hWnd) Local $hDLL = DllOpen("user32.dll") Local $aRet = DllCall('user32.dll', 'DWORD', 'GetWindowThreadProcessId', 'hwnd', $hWnd, 'ptr', 0) $aRet = DllCall('user32.dll', 'handle', 'GetKeyboardLayout', 'DWORD', $aRet[0])DllClose($hDLL)Return $aRet[0] EndFunc ;==>_WinAPI_GetKeyboardLayout $parentPID=run("conhost.exe") $key=_WinAPI_GetKeyboardLayout2($parentPID) MsgBox(0,"",$key) Edited August 25, 2015 by Jfish Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 25, 2015 Author Share Posted August 25, 2015 (edited) @Jfish Thank you for your help. But any command line window doesn't open when I ran the code without any changes. What should I do to control after opening a command line or use already opened window?@Chimp Good idea. I'm trying. Edited August 25, 2015 by Adele Link to comment Share on other sites More sharing options...
Jfish Posted August 25, 2015 Share Posted August 25, 2015 (edited) @Adele - you need to hook the parent process of the console window. I was using "conhost.exe" to do this with the command prompt open and it worked. Then I switched keyboards and ran it again and it picked up the change. Did you use my exact code? I have tried it on two different machines and it worked on both. Edited August 25, 2015 by Jfish Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
BrewManNH Posted August 25, 2015 Share Posted August 25, 2015 Just an FYI to the post in #15, the DLLClose is in the wrong place, it needs to be before the Return statement. Adele and Jfish 2 If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
Jfish Posted August 25, 2015 Share Posted August 25, 2015 Thanks - I missed that. Adele 1 Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt Link to comment Share on other sites More sharing options...
Adele Posted August 25, 2015 Author Share Posted August 25, 2015 (edited) @Adele - you need to hook the parent process of the console window. I was using "conhost.exe" to do this with the command prompt open and it worked. Then I switched keyboards and ran it again and it picked up the change. Did you use my exact code? I have tried it on two different machines and it worked on both.Yes, I did. I run exactly you've given code without modify. Only a MsgBox opens. Command Line window doesn't come. When I changed conhost.exe being cmd.exe, it opens but this time the same issue happens. I use Windows 7 (x64). I can show the issue with Teamviewer or capturing a video.Func _WinAPI_GetKeyboardLayout2($hWnd) Local $hDLL = DllOpen("user32.dll") Local $aRet = DllCall('user32.dll', 'DWORD', 'GetWindowThreadProcessId', 'hwnd', $hWnd, 'ptr', 0) $aRet = DllCall('user32.dll', 'handle', 'GetKeyboardLayout', 'DWORD', $aRet[0]) DllClose($hDLL) Return $aRet[0] EndFunc ;==>_WinAPI_GetKeyboardLayout $parentPID=run("conhost.exe") $key=_WinAPI_GetKeyboardLayout2($parentPID) MsgBox(0,"",$key) Edited August 26, 2015 by Adele Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now