本文旨在对前文的遗漏之处做一个patch,继而详细和大家讨论一下输入法相关的内容,毕竟给中国人用的程序难免会遇到打字的需求,提到打字必然会遇到输入法。
首先是对前文的一个补遗,如果你直接copy前文的代码执行可能会发现本没有出现想象中的鼠标一点,输入法就变了,为啥呢。因为我漏掉了一个步骤,也就是对输入法状态的重置。
需要在调用ImmSetConvertionStatus前对要切换输入法的控件设置 ImeMode=ImeMode.On。
那么这个ImeMode究竟起到什么作用呢,众所周知,在winform的TextBox等控件(包括MaskedTextBox)都包含了一个ImeMode的属性,这个属性其实就是在底层调用了ImmSetConvertionStatus方法来设置输入法为指定的几个枚举值:
图1
图2
根据Reflector的结果发现其中对这个枚举进行了细化
static ImeModeConversion() { japaneseTable = new ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Off, ImeMode.Off, ImeMode.Hiragana, ImeMode.Hiragana, ImeMode.Katakana, ImeMode.KatakanaHalf, ImeMode.AlphaFull, ImeMode.Alpha }; koreanTable = new ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Alpha, ImeMode.Alpha, ImeMode.HangulFull, ImeMode.Hangul, ImeMode.HangulFull, ImeMode.Hangul, ImeMode.AlphaFull, ImeMode.Alpha }; chineseTable = new ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Off, ImeMode.Close, ImeMode.On, ImeMode.OnHalf, ImeMode.On, ImeMode.OnHalf, ImeMode.Off, ImeMode.Off }; unsupportedTable = new ImeMode[0]; }<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->
由此,如果我们只需要设置输入法的全角半角,或者日文输入法的平假名片假名切换就只需要调用 TextBox或者类似控件的ImeMode属性就行了。不过根据Reflector得到的代码我发现其实设置ImeMode来调用ImmSetConvertionStatus的时候Sentence的值恒为0,那么也就是说如果是要切换的日语或者中文的组句特性的话就不能使用ImeMode属性而是用前文的调用win32api的方式来实现。
根据之前的讨论我们可以发现IMM和IME的关系,IMM也就是操作系统的文字服务,只有东亚版本的windows才有,而IME就是输入法的实现程序,包括微软拼音,智能ABC,五笔之类的都是IME的程序,IME注册到IMM中,由IMM来决定当前使用的IME程序,而用户不能直接和IME打交道,而只能通过IMM提供的api接口,比如我们之前用到的ImmSetConvertionStatus。典型的代理模式应用
当然IMM提供的API函数还是IME程序和IMM交互的接口,如果我们要实现自己的输入法的话就只用通过这些接口就行了。
附一:
Mode 和Setence值的含义,按位定义
| 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 |
|_98(me)保留_|_中文标点_|_自定义字符_|_不转换_|_软键盘_|_韩(汉字)_|_内码_|_日罗马_|_全角_|_片假名_|_本地语言_|
| 1/0 | 1/0 | 1/0 | 1/0 | 1/0 | 1/0 |
|_逐键提示_|_词语联想_|_自动模式_|_单字模式_|_多个子句_|_没有组句_|
我在上一篇中的表中, 片假名半角的mode值是19,换成2进制就是10011,查表得到的就是
内码|半角|片假名|本地语言
正好符合。