https://ask.csdn.net/questions/764368?utm_medium=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-2.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task--2~all~first_rank_v2~rank_v29-2.nonecase
c# winform 如何在 win10系统中设置输入法切换
当前网络上提供的解决方案,都是使用InputLanguage类提供的方法,但是这种方法在win10操作系统中是**获取不到**输入法列表的,请问有什么别的方式可以获取设置输入法?
经过我实际测试,在WIN10下,**InputLanguage**只能取到中文、英文输入,不能检测到具体的输入法;另外,网上提供的读**取注册表的**方式,在WIN10下也行不通,注册表中根本没有相关的项。如下:
for (int i=0 ; i< TotalKbLayout ; i++)
{
string RegKey=String.Format("System//CurrentControlSet//Control//Keyboard Layouts//{0:X8}",KbList[i]);
RegistryKey rk=Registry.LocalMachine.OpenSubKey(RegKey);
if (rk==null)
continue;
string ImeName=(string)rk.GetValue("layout text");
if (ImeName==null)
continue;
FImes.Add(ImeName, KbList[i]);
}
在Dot Net中,InputLanguage对象是“提供方法和字段以管理输入语言。无法继承此类。”
InputLanguage对象中InstalledInputLanguages方法获得系统已经安装的输入法;CurrentInputLanguage方法是获取或设置当前输入法;DefaultInputLanguage方法是获取系统的默认输入法。通过InputLanguage对象的这三个方法,可以设置指定的输入法。
而在笔者将程序给他人使用时,却意外的在其中一台机器上报错。由于是已经编译好的程序,而且又不在笔者的身边,故只知道是InputLanguage对象出了问题,而具体的错误编号不知道。
通过QQ远程观看了错误的提示后,第一感觉就是他没有装中文输入法。可是,他明明装了输入法,有搜狗、QQ拼音等。输入法使用也正常。
出于直觉,查看他的“文字服务和输入语言”窗口。正常的应该象下面一样。
可是意外的现象出现了,在他的电脑上这个是一片空白,下面提示一行字“检测到不兼容的键盘驱动程序该对话框已经被禁用”。
在网上搜了搜解决方法。发现由于种种原因,系统注册表中HKEY_LOCAL_MACHINE\SYSTEMCurrentControlSet\Control\Keyboard Layouts的键值下的内容全被删除了。
详情参看“文字服务和输入语言的选项显示空白”。
按照上文的方法,将缺失的注册表部分导入到他的系统中。OK!解决了。不再报错。
由此可以知道,InputLanguage对象是通过访问注册表来控制输入法的。一旦注册表的内容有误。也就导致了错误的产生。
不过,难以理解的是为何注册表出错,而输入法却能正常使用。
开始正文
1、先介绍本文会用到的windows的API,网上有很详细的资料,我这里就只简要说明一下
ImmGetContext(IntPtr hwnd):获取当前正在输入的窗口的输入法句柄
ImmSetOpenStatus(IntPtr himc, bool b):设置输入法的状态
InputLanguage类:提供方法和字段以管理输入语言;这是winform里面自带的输入法管理类,msdn上有详细资料
2、比如本系统安装有两个输入法:搜狗拼音 和 智能 ABC(注意:智能 ABC中间有个空格,用下划线就是要明确对比出来)。
3、使用InputLanguage类来显示指定的输入法。
思路很简单:先获取到操作系统中安装的所有输入法列表,然后循环列表,比对指定的输入法名称(名称可以设置在配置文件中,安装的时候,根据不同人的需要配置成不同的输入法),然后把找到的输入法设为当前输入法,代码如下:
- //设置“搜狗拼音”为当前输入法
- foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
- {
- if (item.LayoutName.Contains("搜狗拼音"))
- {
- InputLanguage.CurrentInputLanguage = item;
- break;
- }
- }
- //设置“智能 ABC”为当前输入法
- foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
- {
- if (item.LayoutName.Contains("智能 ABC"))
- {
- InputLanguage.CurrentInputLanguage = item;
- break;
- }
- }
- //设置系统默认输入法为当前输入法
- InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
3、解决输入法被禁用的假象。
思路也很简单,只需要重新激活输入法就行了,这里就用到上面的API方法了。
首先声明一个委托:
- private delegate void fixImeDele();
- private fixImeDele _fixime;
然后定义委托要实现的事情。
- fixime = delegate
- {
- IntPtr HIme = ImmGetContext(this.Handle);
- ImmSetOpenStatus(HIme, true);
- };
最后执行委托就行了哦。
- this.BeginInvoke(fixime);
最后完整代码如下:
- public partial class Form1 : Form
- {
- [DllImport("imm32.dll")]
- public static extern IntPtr ImmGetContext(IntPtr hwnd);//获取当前正在输入的窗口的输入法句柄
- [DllImport("imm32.dll")]
- public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);//设置输入法的状态
- private delegate void fixImeDele();
- private fixImeDele fixime;
- public Form1()
- {
- InitializeComponent();
- }
- private void txt搜狗拼音_Enter(object sender, EventArgs e)
- {
- //int index = InputLanguage.InstalledInputLanguages.IndexOf(InputLanguage.CurrentInputLanguage);
- //设置“搜狗拼音”为当前输入法
- foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
- {
- if (item.LayoutName.Contains("搜狗拼音"))
- {
- InputLanguage.CurrentInputLanguage = item;
- break;
- }
- }
- }
- private void textBox3_Enter(object sender, EventArgs e)
- {
- //设置“智能 ABC”为当前输入法
- foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
- {
- if (item.LayoutName.Contains("智能 ABC"))
- {
- InputLanguage.CurrentInputLanguage = item;
- break;
- }
- }
- }
- private void txt系统默认_Enter(object sender, EventArgs e)
- {
- //设置系统默认输入法为当前输入法
- InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
- }
- private void txtTrue_Enter(object sender, EventArgs e)
- {
- fixime = delegate
- {
- IntPtr HIme = ImmGetContext(this.Handle);
- ImmSetOpenStatus(HIme, true);
- };
- this.BeginInvoke(fixime);
- }
- private void txtFalse_Enter(object sender, EventArgs e)
- {
- fixime = delegate
- {
- IntPtr HIme = ImmGetContext(this.Handle);
- ImmSetOpenStatus(HIme, false);
- };
- this.BeginInvoke(fixime);
- }
- }
再给大家分享一个小问题的解决方法
wihform 默认的 ImeMode 值是NoControl
这不适合中文输入.
因为例如: 你每到一个控件都要切换一下输入法.
我们应该把父窗口 及所有子窗口 的 ImeMode 值 设置为 On
可是这样有个问题就是 它总是全角状态.
解决办法是:
在每个窗休的 Desinger.cs文件里找到
- this.ImeMode = System.Windows.Forms.ImeMode.On;
替换为
- this.ImeMode = System.Windows.Forms.ImeMode.OnHalf;
这样就ok了.