在我的应用程序中,我们使用Form作为容器,然后进行定制的NativeWindow。
我需要显示一个带有搜索文本框的弹出窗口。每当我显示此弹出窗口时,我的IME输入都会从中文/日语切换到英语模式。根据{{3}}之类的文章,输入上下文应该是针对每个用户还是针对每个线程,为什么我的输入会在同一应用程序中更改? (我正在Windows 10上进行测试)
我试图通过这样做来使主应用保持活动状态,这将阻止输入切换,但是当我显示它时,我的搜索框将不再有键盘输入,因此我无法使用此方法:
protected override void WndProc(ref System.Windows.Forms.Message m) {
switch(m.Msg) {
case (int)WM.ACTIVATE:
if(m.WParam.ToInt64() == 1) {
UserMethods.SetActiveWindow(PopupOwner.Handle);
}
break;
}
base.WndProc(ref m);
}
当我的活动窗口改变时,输入似乎会切换。但是我的搜索框需要抓住键盘,因此我相信我没有其他选择,只能更改活动窗口。
我还尝试创建自己的this,覆盖CanEnableIme并设置ImeMode,但这些方法都无法完美运行,如果有帮助,我可以解释细节。
注意:我的搜索框是自定义的文本编辑器,而不是表单文本框控件;我通过处理诸如input context之类的系统消息来使其处理IME输入,但是我没有修改输入上下文,而只是从中读取内容。
当我更改活动窗口时,如何保持IME输入模式不变?
答案 0 :(得分:0)
我仍然不知道为什么我的输入会在应用程序内切换。
但是要在显示带有搜索框的弹出窗口后保持IME模式不变,我会在激活弹出窗口之前捕获IME状态,并在激活弹出窗口后修改IME状态。像这样:
var imeOpened = false;
//get ime status
var hImc = ImmGetContext(popup.handle);
if(hImc != IntPtr.Zero) {
imeOpened = ImmGetOpenStatus(hImc);
}
Showpopup();
//open ime if it was opened
if(hImc != IntPtr.Zero) {
if(imeOpened) ImmSetOpenStatus(hImc, true);
ImmReleaseContext(popup.handle, hImc);
}
在我的应用中,我有一个一次性捕虫器,这使它变得更加干净:
using(TrapOpenedIme(popup.handle)) Showpopup()
注意:ImmSetConversionStatus
和ImmGetConversionStatus
对我不起作用。
这是一个hacky修复,但是总比没有好:(