Basically, what I am trying to do is to have GetKeyboardLayoutName return the keyboard ID (KLID) of other processes. By default, it retruns only the keyboard ID for my app windo
I figured out a workaround in order to be able to retrieve the keyboard layout for another application. The process is simple:
Getting the HKL of the keyboard language in the other app using GetKeyboardLayout. To get the handle of the other app, you can use GetForegroundWindow to get the handle of the window and then GetWindowThreadProcessId to get the handle of the process having the previously retrieved window handle.
Setting the previously extracted HKL as the keyboard handle of my application, using ActivateKeyboardLayout.
Getting the keyboard language ID (KLID) of my application.
In the end, my application will use the same keyboard language as the other application, and from my application I can easily extract the KLID. Here is the sample code I use in my project. Hope it helps you too.
using System.Runtime.InteropServices;
...
StringBuilder Input = new StringBuilder(9);
[DllImport("user32.dll")]
static extern uint GetKeyboardLayoutList(int nBuff, [Out] IntPtr[] lpList);
[DllImport("user32.dll")]
private static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);
[DllImport("user32.dll")]
static extern bool GetKeyboardLayoutName([Out] StringBuilder pwszKLID);
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
public static extern int ActivateKeyboardLayout(int HKL, int flags);
private static extern bool PostMessage(int hhwnd, uint msg, IntPtr wparam, IntPtr lparam);
private static uint WM_INPUTLANGCHANGEREQUEST = 0x0050;
private static int HWND_BROADCAST = 0xffff;
private static uint KLF_ACTIVATE = 1;
...
public StringBuilder GetInput()
{
IntPtr layout = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));
ActivateKeyboardLayout((int)layout, 100);
GetKeyboardLayoutName(Input);
return Input;
}
public void SetInput(string InputID)
{
PostMessage(HWND_BROADCAST, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, LoadKeyboardLayout(InputID, KLF_ACTIVATE));
}
The method GetInput()
returns a StringBuilder which can be asily converted to a string using ToString()
and then be used to set the keyboard language using a method like SetInput()
.