如何获取Microsoft Edge和ApplicationFrameHost.exe中托管的其他Windows的键盘布局 [英] How to obtain keyboard layout for Microsoft Edge and other windows hosted in ApplicationFrameHost.exe

查看:467
本文介绍了如何获取Microsoft Edge和ApplicationFrameHost.exe中托管的其他Windows的键盘布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知,Windows的键盘布局是特定于线程的.当布局更改时,shell会将消息调度到前台线程.因此,如果要获取最新的全系统键盘布局,则必须执行以下操作:

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);

这对于大多数本机Windows应用程序都适用.

This works fine for most native Windows apps.

但是,UWP应用程序和包括Microsoft Edge在内的一些系统应用程序将其窗口托管在ApplicationFrameHost.exe中.这导致::GetForegroundWindow()返回上述进程的窗口,从而导致一些奇怪的问题,包括对前台进程的错误检测和无法检测实际的键盘布局.

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.

ApplicationFrameHost.exe的线程根本不会对系统范围的键盘布局更改做出反应.看来他们没有托管实际的聚焦UI元素. ::GetForegroundWindow()仅返回框架窗口,但是实际的UI元素具有其自己的线程,并且可能由其自己的进程托管.因此,前景框架窗口根本没有获得相应的布局更改消息,并且其线程具有与之相关的陈旧的HKL.

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.

如何检测到前台进程的正确HKL?

How can I detect the correct HKL of the foreground process?

推荐答案

诀窍是完全不再依赖GetForegroundWindow()方法.

The trick was to stop relying on the GetForegroundWindow() method altogether.

相反,我通过使用古怪且违反直觉的方法解决了该问题,但是

Instead, I solved the problem by utilising the quirky and counter-intuitive, but documented specific usecase of GetGUIThreadInfo().

如果传递零作为该函数的第一个参数,它将返回有关前台线程的信息,即正在接收实际用户输入的信息!

If you pass zero as the first argument to this function, it will return the information for the foreground thread – the one that is receiving the actual user input!

此线程还将从外壳程序中及时接收与HKL相关的消息,因此键盘布局不会过时.

This thread will also receive timely HKL-related messages from the shell, so the keyboard layout will not be stale.

GUITHREADINFO gti = { sizeof(GUITHREADINFO) };

// fetching the foreground thread info
::GetGUIThreadInfo(0, &gti);

// you may also fallback to other window handles in the GUITHREADINFO
// if the `hwndFocus == NULL`
const DWORD thread = ::GetWindowThreadProcessId(gti.hwndFocus, NULL);
const HKL layout = ::GetKeyboardLayout(thread);

这篇关于如何获取Microsoft Edge和ApplicationFrameHost.exe中托管的其他Windows的键盘布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆