c# - 显示弹出窗口时如何防止 IME 输入切换?
问题描述
在我的应用程序中,我们使用Form作为容器,然后我们制作定制的NativeWindow。
我需要显示一个带有搜索文本框的弹出窗口。每当我显示此弹出窗口时,我的 IME 输入将从中文/日文切换到英文模式。基于这样的文章,输入上下文应该是每个用户或每个线程,为什么我的输入会在我的同一个应用程序中改变?(我在 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);
}
当我的活动窗口发生变化时,输入似乎会切换。但是我的搜索框需要抓取键盘,所以我相信我别无选择,只能更改活动窗口。
我还尝试创建自己的输入上下文,覆盖 CanEnableIme 并设置 ImeMode,这些都不是完美的,如果有帮助,我可以解释细节。
注意:我的搜索框是自定义的文本编辑器,不是表单文本框控件;我通过处理这样的系统消息让它处理 IME 输入,但我没有修改输入上下文,只是从中读取。
更改活动窗口时如何保持 IME 输入模式保持不变?
解决方案
我仍然不知道为什么我的输入会在我的应用程序中切换。
但是为了在显示带有搜索框的弹出窗口后保持 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修复,但总比没有好:(
推荐阅读
- elasticsearch - 为文档中的所有字段添加顶级键
- android - 使用自定义相机捕捉帧
- sql - 排名函数:如何“重新开始”计数
- excel - 在工作簿之间传输数据时,如何解决我的 For Next 循环问题?
- stm32 - 为 STM32 项目合并两个 System Workbench
- javascript - 如何检测 MySql 中是否未选择任何内容?
- aws-lambda - Amazon Cognito B2B SaaS 最佳实践?
- typescript - 打字稿:扩展/覆盖类类型定义
- python-3.x - 在不删除所有内容的情况下修改 csv 文件的特定行的最佳方法是什么?
- c# - 如果某个国家/地区更改了夏令时设置,TimeZoneInfo 会发生什么情况?