How to catch the keyboard layout switch event?

Just starting out? Need help? Post your questions and find answers here.
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

How to catch the keyboard layout switch event?

Post by AZJIO »

Sometimes "Hook" doesn't work.

Code: Select all

EnableExplicit

; Structure KBDLLHOOKSTRUCT
; 	vkCode.l
; 	scanCode.l
; 	flags.l
; 	time.l
; 	*dwExtraInfo.Long
; EndStructure


Global hHook

Procedure KeyboardHook(nCode, wParam, *kc.KBDLLHOOKSTRUCT)
	Static x
	Static c
	If nCode = #HC_ACTION
		
		Select *kc\vkCode
			Case 160
				x | 1
; 				ProcedureReturn 1 ; return does not transfer the event to the queue, but catches it on itself
			Case 164
				x | 2
			Default
				x = 0
		EndSelect
		If x = 2
			c + 1
			Debug c
			; here I can query the current layout at the moment the keys are pressed
		EndIf
	EndIf
	ProcedureReturn CallNextHookEx_(#Null, nCode, wParam, *kc)
EndProcedure

If OpenWindow(0, 0, 0, 220, 100, "Example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  hHook = SetWindowsHookEx_(#WH_KEYBOARD_LL, @KeyboardHook(), #Null, 0)
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
				UnhookWindowsHookEx_(hHook)
				CloseWindow(0)
				End
		EndSelect
	ForEver
EndIf
This requires requesting changes 5 times per second.

Code: Select all

#Window = 0
#Timer = 0
Define flgTimer = 200
Define Layout, old_Layout

If OpenWindow(#Window, 0, 0, 220, 100, "Example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	If flgTimer
		AddWindowTimer(#Window, #Timer, flgTimer)
	EndIf
	
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Timer
				If EventTimer() = #Timer
					Layout = GetKeyboardLayout_(GetWindowThreadProcessId_(GetForegroundWindow_(), 0))
					If old_Layout <> Layout
						old_Layout = Layout
						Debug Layout >> 16
					EndIf
				EndIf
			Case #PB_Event_CloseWindow
				CloseWindow(#Window)
				End
		EndSelect
	ForEver
EndIf
If I open the cmd.exe console, I can't get the keyboard layout even though the system tray text switches
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: How to catch the keyboard layout switch event?

Post by RASHAD »

Catch Input language change while running CMD.exe

Code: Select all

Global prog,kb,oldkb
prog = RunProgram("cmd.exe","","",#PB_Program_Open)
While ProgramRunning(prog)
  kb = GetWindowThreadProcessId_(GetForegroundWindow_(),0)
  kb = GetKeyboardLayout_(kb)
  If kb <> oldkb 
    oldkb = kb
    Delay(1000)
    Debug Str(oldkb >> 16)
  EndIf
Wend
Egypt my love
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: How to catch the keyboard layout switch event?

Post by AZJIO »

RASHAD wrote: Sun Mar 24, 2024 4:31 am Catch Input language change while running CMD.exe
It doesn't work for me. How does your code differ from mine in terms of functionality?
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: How to catch the keyboard layout switch event?

Post by breeze4me »

I haven't tried it with PB, but the answer below might be helpful.
https://stackoverflow.com/questions/828 ... is-changed
AZJIO wrote: Sat Mar 23, 2024 7:26 pm If I open the cmd.exe console, I can't get the keyboard layout even though the system tray text switches
The console part is MS's issue.
https://github.com/microsoft/terminal/issues/83
https://stackoverflow.com/questions/292 ... some-cases
https://stackoverflow.com/questions/526 ... pplication
In Windows 8+, conhost.exe is launched using an IOCTL to the ConDrv device, which executes the host as a child of the caller. This has nothing inherently to do with cmd.exe, which is just a shell. Also, for the console window, the process and thread ID returned by GetWindowThreadProcessId is faked based on the console's current effective owner, which is stored as console window data. It's not the thread that really owns the console window, and there is no documented way to query the real thread in the console host process that created the window. –
Eryk Sun
Oct 6, 2018 at 16:39
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: How to catch the keyboard layout switch event?

Post by RASHAD »

I didn't use any Window and forced CMD to be run as Invoker not admin
It works here with Windows 11 x64
It's different than you did
Egypt my love
Post Reply