Wince输入法换肤换语言机制

来源:互联网 发布:淘宝开网店的必备条件 编辑:程序博客网 时间:2024/05/01 09:03

需求描述:
最近由于邦健客户提出新需求:需要在一个系统内同时实现中英文两个语种的输入法。
即,客户的wince系统语言版本是中文,但在其中的应用软件有中文和英文两个版本,所以相应的输入法也需要做调整,做到:应用程序是中文时,出现的是中文界面的输入法;应用程序是英文时,出现的是英文界面的输入法。

相关决策:
由于该需求有助于强化wince输入法的功能,且对后续的维护工作有改进效果,所以承接该需求。

已有资源:
鉴于之前国笔wince输入法的版本已有中文版和英文版,目前要做的就是整合中英文版的代码,兼容中、英版本的皮肤文件,并提供接口供客户随时调用,实现切换皮肤和引擎开关的即时切换。

设计因素:
1, 版本兼容性:包括对系统语言版本的兼容
2, 客户调用接口的便利性:提供通用、灵活的方法来实现客户需要的接口,并且便于测试
3, 稳定性:对原有代码尽可能地减少改动,并最大限度利用现有资源(函数、皮肤文件等)

设计步骤:
1, 考虑到接口的便利性,决定采用发送自定义消息的方式提供语言切换的接口。
2, 第一阶段,整合中英文版本。原有的中文版和英文版的区别,在于一些宏定义。当初也是为了便于管理,把英文版作为中文版的分支独立出来,为版本管理降低了一些反复的宏定义开关修改过程。整合的过程并不复杂,只需要小心地把两个版本不一样的地方分别用宏定义控制即可。
3, 但是单靠语言控制宏不能实现动态的语言版本切换,需要将宏定义改成可以随时更改的变量,所以第二步就是用变量wSystemLangIDPrimary代替宏定义,由变量来决定当前的语言版本,以便修改引擎设置。
4, 变量的赋值有两个途径:
a) 第一个途径是初始化赋值,获取系统语言版本ID,04代表中文,09代表英文。(参考资料:
http://tech.cuit.edu.cn/forum/thread-505-1-6.html

WORD wSystemLangID = GetSystemDefaultLangID();
WORD wSystemLangIDPrimary = PRIMARYLANGID( wSystemLangID );

b) 第二个途径是通过应用程序发送消息更改变量wSystemLangIDPrimary。消息定义如下:
// 应用程序用GB_CHANGE_IM_TYPE消息通知软键盘切换输入法类型[2010.7.22 lishuzhe]
// wparam == GB_SWITCH_IM_TYPE时,lparam的值意义如下:,拼音;2,笔画;3,英文;4,数字;5,字母;6,手写;
// wparam == GB_MOVE_SIP时,lparam = MAKELPARAM(x,y);
// wparam == GB_APP_LANG时,lparam = LANG_CHINESE(0x04)时,代表中文界面;lparam = LANG_ENGLISH(0x09)时,代表英文界面。

#define GB_APP_MSG 0x00CC00CC
enum GB_APP_CONTROL_TYPE{
GB_APP_SWITCH_IM_TYPE = 0,
GB_APP_MOVE_SIP = 1,
GB_APP_LANG = 2
};
当客户想输入法窗口发送消息,
PostMessage( hwnd , GB_APP_MSG , GB_APP_LANG , nLang );
输入法响应消息,修改wSystemLangIDPrimary,隐藏界面,在注册表将isSkinChange一项设置为1,表示下次显示窗口时应该重新读取皮肤文件。
用户再次调出输入法面板时,将读取注册表项isSkinChange,如果为1,则引擎将根据wSystemLangIDPrimary重新初始化,并重新加载皮肤。

5, 如何根据系统语言ID号来选择相应的皮肤:
a) 每套皮肤包括一个png文件和一个gbk文件,其前缀相同,仅后缀不同。其中png文件是带有多层图像数据的图片文件,gbk是含有对应png割图信息的数据文件。用户如果需要全英文界面,则皮肤文件将不会出现中文字符,如果还需要与中文版切换,就需要两套皮肤。因为我们的皮肤文件格式尚未做到可以切换中英文的功能,所以只能将两套皮肤都放在安装目录下,由输入法模块来根据变量wSystemLangIDPrimary来选择。
b) 皮肤的属性包括:颜色、横\竖屏、大小、语言。
i. 大小:现有代码对皮肤大小和横\竖屏的处理都比较完善和智能化处理。初始化模块会加载皮肤文件,读取数据头,获取该套皮肤的宽、高,以及横竖屏。比如屏幕是240X320的,就将安装目录下的所有该分辨率的皮肤加入列表(即为SkinList,包括了皮肤文件的文件名、皮肤大小等)以供选择(获取屏幕信息的函数GetSystemMetrics和SystemParametersInfo)。如果没有完全匹配的皮肤,则选择面积最相近的那一套。
ii. 横\竖屏:同理,横\竖屏也可以通过读取皮肤信息和屏幕属性对比来确定。皮肤文件已经包含了自动变换横竖屏的信息,所以不需要针对横竖屏作额外处理(本处内容与皮肤文件格式与解析有关,暂不赘述)。
iii. 颜色:注册表项SkinColor的值是颜色的名称,比如blue、black、red等,不区分大小写。
iv. 语言:注册表项Language的值是语言的名称,比如English、Chinese等,不区分大小写。
v. 系统启动时,读取注册表项SkinColor和Language,拼接皮肤文件前缀,其格式为:SkinColor_Language_Size,如果SkinColor和Language的值分别是Blue和English,则皮肤文件前缀应该是Blue_English_XXX,其中XXX是大小,一般为wvga、vga、qvga等。拼接好文件前缀后,就在已经读取的适用列表SkinList中进行匹配,找到相应的皮肤文件全名,加载之。
c) 示例:
i. 启动时,输入法模块先获取系统语言ID号,如果wSystemLangIDPrimary是04,则将注册表项Language设置为Chinese。
ii. 然后读取SkinColor和Language,获得最匹配的皮肤文件,根据wSystemLangIDPrimary初始化引擎为中文模式。
iii. 如果用户想切换至纯英文界面,则发送消息
PostMessage( hwnd , GB_APP_MSG , GB_APP_LANG , 09 );
即可。
iv. 输入法收到消息后,更改Language的值为English,设置isSkinChange为1,并隐藏输入法界面。待下一次调出虚拟键盘时,将重新初始化引擎为英文模式,并加载英文皮肤,设置isSkinChange为0。这样就完成了语言和皮肤的切换。
v. 后续如果有用户需要输入法提供换肤功能,则可以发送消息通知输入法修改SkinColor表项值(Language值不变),并设置isSkinChange为1,这样在下一次显示界面时,就可以切换到相应的皮肤上了。