• Dot Net中InputLanguage对象的使用限制


    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

    TCefFastTask.New(TID_UI,切换输入法函数)

    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_MACHINESYSTEMCurrentControlSetControlKeyboard Layouts的键值下的内容全被删除了。

      详情参看“文字服务和输入语言的选项显示空白”。

      按照上文的方法,将缺失的注册表部分导入到他的系统中。OK!解决了。不再报错。

      由此可以知道,InputLanguage对象是通过访问注册表来控制输入法的。一旦注册表的内容有误。也就导致了错误的产生。

      不过,难以理解的是为何注册表出错,而输入法却能正常使用。

    开始正文

    1、先介绍本文会用到的windows的API,网上有很详细的资料,我这里就只简要说明一下

      ImmGetContext(IntPtr hwnd):获取当前正在输入的窗口的输入法句柄

      ImmSetOpenStatus(IntPtr himc, bool b):设置输入法的状态

      InputLanguage类:提供方法和字段以管理输入语言;这是winform里面自带的输入法管理类,msdn上有详细资料

    2、比如本系统安装有两个输入法:搜狗拼音 和 智能 ABC(注意:智能 ABC中间有个空格,用下划线就是要明确对比出来)。

    3、使用InputLanguage类来显示指定的输入法。

      思路很简单:先获取到操作系统中安装的所有输入法列表,然后循环列表,比对指定的输入法名称(名称可以设置在配置文件中,安装的时候,根据不同人的需要配置成不同的输入法),然后把找到的输入法设为当前输入法,代码如下:

    1. //设置“搜狗拼音”为当前输入法
    2. foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
    3. {
    4. if (item.LayoutName.Contains("搜狗拼音"))
    5. {
    6. InputLanguage.CurrentInputLanguage = item;
    7. break;
    8. }
    9. }
    10. //设置“智能 ABC”为当前输入法
    11. foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
    12. {
    13. if (item.LayoutName.Contains("智能 ABC"))
    14. {
    15. InputLanguage.CurrentInputLanguage = item;
    16. break;
    17. }
    18. }
    19. //设置系统默认输入法为当前输入法
    20. InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;

    3、解决输入法被禁用的假象。

      思路也很简单,只需要重新激活输入法就行了,这里就用到上面的API方法了。

      首先声明一个委托:

    1. private delegate void fixImeDele();
    2. private fixImeDele _fixime;

      然后定义委托要实现的事情。

    1. fixime = delegate
    2. {
    3. IntPtr HIme = ImmGetContext(this.Handle);
    4. ImmSetOpenStatus(HIme, true);
    5. };

      最后执行委托就行了哦。

    1. this.BeginInvoke(fixime);

    最后完整代码如下:

    1. public partial class Form1 : Form
    2. {
    3. [DllImport("imm32.dll")]
    4. public static extern IntPtr ImmGetContext(IntPtr hwnd);//获取当前正在输入的窗口的输入法句柄
    5. [DllImport("imm32.dll")]
    6. public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);//设置输入法的状态
    7. private delegate void fixImeDele();
    8. private fixImeDele fixime;
    9. public Form1()
    10. {
    11. InitializeComponent();
    12. }
    13. private void txt搜狗拼音_Enter(object sender, EventArgs e)
    14. {
    15. //int index = InputLanguage.InstalledInputLanguages.IndexOf(InputLanguage.CurrentInputLanguage);
    16. //设置“搜狗拼音”为当前输入法
    17. foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
    18. {
    19. if (item.LayoutName.Contains("搜狗拼音"))
    20. {
    21. InputLanguage.CurrentInputLanguage = item;
    22. break;
    23. }
    24. }
    25. }
    26. private void textBox3_Enter(object sender, EventArgs e)
    27. {
    28. //设置“智能 ABC”为当前输入法
    29. foreach (InputLanguage item in InputLanguage.InstalledInputLanguages)
    30. {
    31. if (item.LayoutName.Contains("智能 ABC"))
    32. {
    33. InputLanguage.CurrentInputLanguage = item;
    34. break;
    35. }
    36. }
    37. }
    38. private void txt系统默认_Enter(object sender, EventArgs e)
    39. {
    40. //设置系统默认输入法为当前输入法
    41. InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
    42. }
    43. private void txtTrue_Enter(object sender, EventArgs e)
    44. {
    45. fixime = delegate
    46. {
    47. IntPtr HIme = ImmGetContext(this.Handle);
    48. ImmSetOpenStatus(HIme, true);
    49. };
    50. this.BeginInvoke(fixime);
    51. }
    52. private void txtFalse_Enter(object sender, EventArgs e)
    53. {
    54. fixime = delegate
    55. {
    56. IntPtr HIme = ImmGetContext(this.Handle);
    57. ImmSetOpenStatus(HIme, false);
    58. };
    59. this.BeginInvoke(fixime);
    60. }
    61. }

    再给大家分享一个小问题的解决方法

    wihform 默认的 ImeMode 值是NoControl

    这不适合中文输入.

    因为例如: 你每到一个控件都要切换一下输入法.

    我们应该把父窗口 及所有子窗口 的 ImeMode 值 设置为 On

    可是这样有个问题就是 它总是全角状态.

    解决办法是:
    在每个窗休的 Desinger.cs文件里找到

    1. this.ImeMode = System.Windows.Forms.ImeMode.On;

    替换为

    1. this.ImeMode = System.Windows.Forms.ImeMode.OnHalf;

    这样就ok了.

  • 相关阅读:
    单调栈
    P1164 小A点菜
    P1156 垃圾陷阱
    P1140 相似基因
    P1136 迎接仪式
    P1133 教主的花园
    P1131 [ZJOI2007]时态同步
    P1130 红牌
    利用SQLite在android上实现增删改查
    利用SQLite在android上创建数据库
  • 原文地址:https://www.cnblogs.com/chinasoft/p/14806944.html
Copyright © 2020-2023  润新知