As we all know, Windows's keyboard layouts are thread-specific. When a layout changes, a message is dispatched to the foreground thread by the shell. So if one wants to obtain the most recent system-wide keyboard layout, one must do something like this:
const HWND foregroundWindow = ::GetForegroundWindow();
const DWORD foregroundThread = ::GetWindowThreadProcessId(foregroundWindow, NULL);
const HKL layout = ::GetKeyboardLayout(foregroundThread);
This works fine for most native Windows apps.
However, UWP applications, and several system apps including Microsoft Edge host their windows in the ApplicationFrameHost.exe
. This causes ::GetForegroundWindow()
to return the window of said process, leading to several curious problems, including misdetection of the foreground process and troubles detecting the actual keyboard layout.
The threads of ApplicationFrameHost.exe
simply don't react to the system-wide keyboard layout change. It seems that they are not hosting the actual focused UI element. ::GetForegroundWindow()
returns only the frame window, but the actual UI element has its own thread and maybe is hosted by its own process. Thus, the foreground framw window is simply not getting the respective layout change messages, and its thread has a stale HKL
associated with it.
How can I detect the correct HKL of the foreground process?