首先,感谢您阅读此主题并提供您的建议。
这是我的问题的详细描述:由于大量遗留代码,我们需要使用 Win32 消息。而对于 UI 部分,我们需要使用 WPF 来现代化我们的外观。UI 的那部分需要将键盘消息引导到旧的遗留组件中。对于没有 IME 的输入消息,我们使用 ComponentDispatcher.ThreadFilterMessage 来获取这些消息,例如 WM_KEYDOWN、WM_CHAR 等。但是对于 IME 输入,我们无法得到对应的 WM_IME_* 消息。我们是否有办法获取这些消息,或者至少获取与 WM_IME_* 消息对应的所有输入文本?
为此,我们尝试了几种方法:首先,WPF 原生方法,如 OnPreviewKeyDown()、OnTextInput()。该解决方案的一个不足之处是我们无法获取 Win32 消息。而且我发现 WPF 不会响应某些特殊键,例如 Space 键不会导致 OnTextInput() 被调用。其次,不同的钩子,如 SetWindowLong()、HwndSource.AddHook()。这些解决方案也不会收到 WM_IME_* 消息。第三,使用 InputMethod 类。我尝试使用 InputMethod.ImeConversionMode 来确定用户输入是否对应于 WM_IME_* 消息。但是你知道它是与 ComponentDispatcher.ThreadFilterMessage 不同的方式,并且违反了几个基本规则。同时,我不确定这两种方式是否有重叠的情况,是否有漏报的情况。
当我使用可以由 TextBoxBase.OnGotKeyboardFocus() 创建的类 ImmComposition 进行调查时,我已经看到 ImmCompositionFilterMessage() 挂钩正在处理 WM_IME_CHAR(0x0286),但未能在我的挂钩中添加它在 base 之后添加。OnGotKeyboardFocus():
public class HookedTextBox : TextBox
{
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
InstallHook();
}
}