Recent

Author Topic: [SOLVED] How to detect keyboard layout?  (Read 2037 times)

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
[SOLVED] How to detect keyboard layout?
« on: September 28, 2018, 08:26:04 am »
I want to make ScrollLock to be On when a kirrilic layout is activated and Off when latin is activated. So I wonder how to „read‟ which layout is selected?
Windows only solution would be enough for me, but it wold be better if it is applicable for Linux.
« Last Edit: November 28, 2018, 12:00:16 pm by CM630 »
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

ASerge

  • Hero Member
  • *****
  • Posts: 997
Re: How to detect keyboard layout?
« Reply #1 on: September 28, 2018, 04:02:39 pm »
I want to make ScrollLock to be On when a kirrilic layout is activated and Off when latin is activated.
Only in your app?

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: How to detect keyboard layout?
« Reply #2 on: November 21, 2018, 11:03:47 am »
No, I want it to behave this way in every app.
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

ASerge

  • Hero Member
  • *****
  • Posts: 997
Re: How to detect keyboard layout?
« Reply #3 on: November 21, 2018, 04:46:53 pm »
No, I want it to behave this way in every app.
To determine: periodically by timer, get the foreground window, its thread ID, and use GetKeyboardLayout.
For setup use SendInput with simulated pressing the Scrolllock.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2030
    • havefunsoft.com
Re: How to detect keyboard layout?
« Reply #4 on: November 21, 2018, 05:07:47 pm »
To determine: periodically by timer, get the foreground window, its thread ID, and use GetKeyboardLayout.
For setup use SendInput with simulated pressing the Scrolllock.
tracking WM_INPUTLANGCHANGE could be a better approach for Windows, rather than timer.

...actually no. It's only being sent to the topmost window.
« Last Edit: November 21, 2018, 05:19:12 pm by skalogryz »
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

GetMem

  • Hero Member
  • *****
  • Posts: 3251
Re: How to detect keyboard layout?
« Reply #5 on: November 21, 2018, 06:27:16 pm »
Try @Serge suggestion(not tested):
Code: Pascal  [Select]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   ActiveWindow: HWND;
  4.   ActiveThreadID: DWord;
  5.   KeyBoardLayOut: HKL;
  6.   Lang: array[0..2] of Char;
  7.   KeyState : TKeyBoardState;
  8.   NeedToChange: Boolean;
  9. begin
  10.   ActiveWindow := GetForegroundWindow;
  11.   ActiveThreadID := GetWindowThreadProcessId(ActiveWindow, nil);
  12.   KeyBoardLayOut := GetKeyboardLayout(ActiveThreadID);
  13.   GetKeyboardstate(KeyState);
  14.   GetLocaleInfo(LoWord(KeyBoardLayOut), LOCALE_SENGLANGUAGE, Lang, 2);
  15.   if UpperCase(Lang) = 'EN' then
  16.     NeedToChange := KeyState[VK_SCROLL] = 0
  17.   else
  18.     NeedToChange := KeyState[VK_SCROLL] = 1;
  19.   if NeedToChange then
  20.   begin
  21.     Keybd_Event(VK_SCROLL, 45, KEYEVENTF_EXTENDEDKEY, 0);
  22.     Keybd_Event(VK_SCROLL, 45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  23.   end;
  24. end;  


PS: Timer interval is 1000. Don't forget to change "EN" to whatever language you like. Now the scroll lock will be switched on for English. Windows only...
« Last Edit: November 21, 2018, 06:33:06 pm by GetMem »

sash

  • Full Member
  • ***
  • Posts: 148
Re: How to detect keyboard layout?
« Reply #6 on: November 21, 2018, 09:48:28 pm »
I want to make ScrollLock to be On .... but it wold be better if it is applicable for Linux.

If you're about LED indicator, on my Linux (XFCE, although it is configurable in xorg) this works right out of the box: whenever I have Cyrillic layout on, I also have ScrollLock LED on.
« Last Edit: November 21, 2018, 09:55:58 pm by sash »
Lazarus 1.8.4 Unversioned directory FPC 3.0.4 x86_64-linux-gtk2

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: How to detect keyboard layout?
« Reply #7 on: November 22, 2018, 12:14:02 pm »
...Don't forget to change "EN" to whatever language you like. Now the scroll lock will be switched on for English. Windows only...
I added Windows in Uses.
And as you wrote, I changed if UpperCase(Lang) = 'EN' then to if LeftStr(UpperCase(Lang),2) = 'EN' then
Not Scroll Lock flickers when English layout is selected. I have not debugged, but flickering seems even better ;)

Edit: It dos not flicker when the Lazarus application itself is shown.
« Last Edit: November 22, 2018, 12:15:56 pm by CM630 »
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: How to detect keyboard layout?
« Reply #8 on: November 28, 2018, 12:00:03 pm »
Thanks to everyone!I have marked this is solved since I got an answer „How to detect keyboard layout‟.
Still I cannot figure out how to set CapsLock on and off, but I will create a separate thread for that if necessary.
Anyway a GetKeyboardState(KeyState);  seems to be missing in @GetMem's code.
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

GetMem

  • Hero Member
  • *****
  • Posts: 3251
Re: [SOLVED] How to detect keyboard layout?
« Reply #9 on: November 28, 2018, 12:03:13 pm »
Anyway a GetKeyboardState(KeyState);  seems to be missing in @GetMem's code.
Look at line 13.  :)


Still I cannot figure out how to set CapsLock on and off
Same way you did with Scroll Lock:
Code: Pascal  [Select]
  1. uses windows;
  2.  
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. begin
  5.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY, 0);
  6.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  7. end;
« Last Edit: November 28, 2018, 12:08:24 pm by GetMem »

indigo80

  • New member
  • *
  • Posts: 18
Re: [SOLVED] How to detect keyboard layout?
« Reply #10 on: November 28, 2018, 02:11:52 pm »

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] How to detect keyboard layout?
« Reply #11 on: November 30, 2018, 10:02:27 am »

Still I cannot figure out how to set CapsLock on and off

Same way you did with Scroll Lock:
Code: Pascal  [Select]
  1. uses windows;
  2.  
  3.  
  4. procedure TForm1.Button1Click(Sender: TObject);
  5. begin
  6.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY, 0);
  7.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  8. end;


This code toggles CapsLock.
So I need to know current state of CapsLock, in order to decide if I should toggle it.

But, GetKeyboardState(KeyState);  returns 4 values: 0;1; 128 or 129.
0 = Off
1 = On
128 = Scroll lock is pressed. It was ON before being pressed.
129 = Scroll lock is pressed. It was OFF before being pressed.

But
Code: Pascal  [Select]
  1.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY, 0);
  2.   Keybd_Event(VK_CAPITAL, 45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);

leaves KeyState in 128 or 129, still I have not found how 128 or 129 are set, but KeyState might be both 128 and 129 in ON state (and vice versa).


Thanks, @indigo80, but I still do not know how to detect keyboard layout in Linux. And currently, Windows is what bothers me, Linux has support for what I want (as @Sash wrote).

« Last Edit: November 30, 2018, 10:06:27 am by CM630 »
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

GetMem

  • Hero Member
  • *****
  • Posts: 3251
Re: [SOLVED] How to detect keyboard layout?
« Reply #12 on: November 30, 2018, 10:24:49 pm »
@CM630
Quote
This code toggles CapsLock.
So I need to know current state of CapsLock, in order to decide if I should toggle it.

But, GetKeyboardState(KeyState);  returns 4 values: 0;1; 128 or 129.
0 = Off
1 = On
128 = Scroll lock is pressed. It was ON before being pressed.
129 = Scroll lock is pressed. It was OFF before being pressed.
I'm not following you, what are you saying is not making sense. Attached project works for you or not?

CM630

  • Hero Member
  • *****
  • Posts: 856
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] How to detect keyboard layout?
« Reply #13 on: December 04, 2018, 04:51:34 pm »
I have added a couple of lines and a label to your code.
Leftmost bit (bit 7) in KeyState seems to indicate if key is pressed.
You can try your own app- when key is pressed indicator on the keyboard and indicator on the app mismatch in one of the direction.


When application itself is working- everything is ok, but when ScrollLock is toggled outside it (another app is focused)- bit 7 starts to make troubles.
I will try to ignore bit 7.
Лазар 1,8,2;W7 64bit or XP 32bit;FPC3,0,4;rev 57369

GetMem

  • Hero Member
  • *****
  • Posts: 3251
Re: [SOLVED] How to detect keyboard layout?
« Reply #14 on: December 04, 2018, 05:54:14 pm »
One more try...