CEGUI 输入法窗话把现
CEGUI 输入法窗口实现游戏中经常要输入汉字,但当我们游戏没有自己实现输入法窗口时,windows会使用用户安装
CEGUI 输入法窗口实现
游戏中经常要输入汉字,但当我们游戏没有自己实现输入法窗口时,windows会使用用户安装的输入法,但这个输入法窗口只会显示在游戏窗口外头,而且当我们游戏全屏时(真全屏,不是那种窗口式的假全屏),屏幕上无法显示其他程序的窗口,也就看不到任何输入法窗口了。此时玩家输入文字,无法看到候选词列表,用户输入将会变的举步维艰。所以一般网络游戏都会有一个游戏内置的输入法窗口。由于这个输入法窗口式游戏程序自己渲染的,不管全屏与否都会正常显示。如何实现游戏内置输入法窗口呢?
通过查阅相关资料,以及个人实践,我完成了一个教学版的输入法窗口实现。实现游戏内置输入法窗口并不难,和游戏相关的逻辑其实比较简单,难点主要在熟悉Windows对于输入法的消息管理,以及相关模块的API。首先让我们看一下Windows对于输入法的一下消息及相关API。
WM_INPUTLANGCHANGE
根据字面意思,就是输入语言切换消息。实际上就是当我们更换输入法就会发出这个消息。我们通过监听这个消息,来显示隐藏游戏内置输入法窗口。因为当我们切换成Windows的【EN】输入法时,我们是纯英文输入,无需任何输入法窗口,所以这时我们要隐藏我们的输入法窗口。如何判断是不是【EN】输入法呢?
ImmEscape()
此API可以获取当前输入法的一些基本信息,如输入法的名称等。具体API的用法MSDN写的十分清楚了,这里就不讲解了。这里需要注意【EN】输入法是没有名称的,所以可以当使用 ImmEscape() 获取输入法名称失败时,我们就隐藏游戏内置输入法,因为之时表明用户切换到了【EN】输入法。
WM_IME_COMPOSITION
有IME( Input Method Edit )前缀的消息都是输入法消息。此消息表明输入法混合状态改变。什么是混合?什么是混合状态?混合是指通过多个键盘按键组合生成一些其他语言字符过程。所以混合状态可以认为是一些和混合相关记录信息,如输入的拼音改变,输入法候选词列表改变。此消息是个消息大类,包含了很多子消息。多个子消息可以组合在一起,存放在消息的 lParam 参数中。我们可以通过 ( lParam & 子消息 )来判断此消息中是否包含该子消息。下面看一下和我们相关的两个子消息。
GCS_COMPSTR
此消息是输入法“混合字符”改变的消息。什么是混合字符呢?当我们用搜狗等中文输入法的时候,我们打汉字都是有拼音,我们通过打拼音混合出汉字,拼字字符串就是混合字符。所以说 ni 是混合字符, nih 也是混合字符,由 ni 改变成 nih,表明用户添加或者删除了拼音。混合字符对我们输入法窗口是很有用的。你用搜狗输入法打个字会发现,第一行显示的就是混合字符。所以我们通过监听这个消息,绘画输入法窗口中用户输入的拼音。
ImmGetCompositionStringW()
此API比较强大,通过传入一些Flag,可以获取输入法的混合字符,以及混合之后的生成字符等。API在MSDN中讲的比较清楚,而且后面我会附带源码,可以参考一下我是如何使用的(^-^)。
GCS_RESULTSTR
此消息是用户通过输入法生成了某些字符,这些字符需要输入到对应的编辑框中。另外再说一点,CEGUI支持中文显示之后,并不能通过输入法输入中文字符,这是因为CEGUI没有监听这个消息。所以在这个消息中,我们将把IME生成中文字符注入到CEGUI中( CEGUI::System::getSingleton().injectChar() )。获取生成字符也是通过ImmGetCompositionStringW()获取。
WM_IME_NOTIFY
此消息包括IME的各种通知消息,如候选词列表改变,打开关闭,圆角半角切换等。暂时,这里面我们比较关心的是候选词列表的打开,改变,关闭消息。候选词列表我们应该都知道,当我们输入 ni 的时候搜狗输入法会给出5个候选词。我们需要从中选择一个。候选词列表也是输入法窗口渲染中最重要的模块。其中用到的API是:
ImmGetCandidateListW()
相关信息查阅MSDN,参考一下我的用法可能会理解的快一点。其中最主要是一个以char [1]数组结尾结构体,一般用于变长结构体。它将候选词的偏移量以及候选词字符串全都放在结构体最后。
IME相关的Windows只是我们大体已经了解了。现在介绍一下如果使用CEGUI实现这个教学班的输入法窗口。让我们分析一下:
首先,我们需要一个能显示多项候选词列表,以及混合字符串的控件。我们自定义控件当然可以,但是作为教学,我们尽可能的利用存在的控件。其实我觉得CEGUI::Listbox已经很合适了,我们将混合字符串放在列表框的最下层,然后将候选词列表从上到下排列。但直接使用列表框,不能很好的提供便利函数,比如设置候选词列表,更改字符串,以及一些可能存在的输入法窗口状态。所以我觉得派生自列表框,服用列表框的LookNFeel,WindowRenderer。这样我们需要做的只是添加一个新的控件类。
基本上就这些了。下面是IME控件类的实现代码:
如何疑问,敬请咨询。