以下内容摘自http://msdn.microsoft.com/zh-cn/goglobal/bb688135.aspx

在 Win32 中处理输入语言的方法

Microsoft Developer Network (MSDN) 文档(位于 http://msdn.microsoft.com)和编程 API 用一种名为“输入法区域设置标识符”的变量类型代表输入语言,它在先前的文档中被称为“键盘布局处理”(HKL) 并且现在仍被用作类型标识符。HKL 是一种古老的名称,当时只能从键盘进行输入。输入法区域设置标识符名称是一个 32 位的值,它由语言标识符(低 WORD)和设备标识符(高 WORD)的十六进制值组成。(参见下方的图 7。)例如,美国英语的语言标识符为 0x0409,因此美国英语主布局被命名为 "00000409"。美国英语布局的变体(例如 Dvorak 布局)被命名为 "00010409"、"00020409" 等。设备标识符并不仅限于键盘和 IME;现在可通过一些较复杂的机制(例如语音和文字识别引擎)来输入数据。例如,在 Windows XP 中作为一种系统服务提供的 Microsoft Windows Text Services Framework (TSF),它可以实现与来源无关的高级文字输入。(有关 TSF 的更多信息,请参阅 Text Services Framework)。

图 7:代表输入语言的 HKL 变量。


处理输入语言最简单的方式是在需要用户输入的所有场合都使用操作系统提供的标准控件。例如,通过使用 Unicode 编辑控件或 Rich edit 控件,可以使应用程序能够处理多种语言的文字输入。操作系统会以一种对应用程序透明的方式自动处理输入语言。文字 API 使用的是一种标准的多行编辑控件,它可以避免处理输入语言时的麻烦。

对于一些需要完全控制输入语言处理方式的高级应用程序(例如文本编辑器),它们应该监视(并能够响应)用户的改动。当用户通过单击任务栏上的语言指示符或按下“左边 Alt+Shift”键来选择某种输入语言时,输入语言不会自动改变 – 两个操作都会生成一个活动的应用程序必须接受或拒绝的请求。为了响应热键组合或鼠标单击任务栏上的语言指示符后产生的事件,系统会向焦点窗口发送一个 WM_INPUTLANGCHANGEREQUEST 消息,如下图所示。如果应用程序接受该消息并将其传递给DefWindowProc,系统将启动切换输入语言的操作并发送一个 WM_INPUTLANGCHANGE 消息。如果输入法是 Text Services Framework (TSF) 的一部分,则此过程会略有不同,这时只发送 WM_INPUTLANGCHANGE。当系统成功完成改变后,会生成一个 WM_INPUTLANGCHANGE 消息。WM_INPUTLANGCHANGE 消息的 lParam 变量包含新输入语言的输入法区域设置标识符(即 HKL)。

图 8:WM_INPUTLANGCHANGEREQUEST 和 WM_INPUTLANGCHANGE 消息传播流程图。


不支持多语言的应用程序会拒绝 WM_INPUTLANGCHANGEREQUEST 消息。它可能会拒绝任何或全部 WM_INPUTLANGCHANGEREQUEST 消息,也可能会先执行一些测试。例如,此消息的 wParam 变量是一个 Boolean 值 bLangInSystemCharset,它将指出请求的输入语言是否能够在当前的系统区域设置中呈现出来。在处理 Unicode 应用程序时呈现输入语言并不麻烦,但是,非 Unicode 应用程序应该监视此值(实际上也是如此),否则它们会显示错误的字符。

与生成 WM_INPUTLANGCHANGEREQUEST 消息来响应用户请求的系统类似,应用程序也会通过调用 ActivateKeyboardLayout API 来启动改变输入语言的操作。如果用户编辑包含拉丁文和希腊文的文档,当用户将插入点从拉丁文字移动到希腊文字时,将会自动激活希腊文输入法。(参见下方的表 4。)同样,当此用户将插入点移回拉丁文字时,应用程序将激活默认的基于拉丁文的输入法。

图 9:当光标被定位到希腊文文本流中时,活动的键盘布局会切换到希腊文。


处理输入法的其他 Win32 API 如下方的表 4 所示:

表 4


在设计允许用户切换键盘布局的功能时,要清楚由于不同布局的键盘上字母排列各不相同,因此用来生成快捷键组合的按键可能也会有所变化。例如,法语键盘默认为 AZERTY 布局,而英语布局采用 QWERTY 映射。因此,建议您在快捷键组合中使用数字和功能键(F4、F5 等),而不要使用字母。

除了使您的应用程序能够处理各种输入语言外,您还需要使其能够支持 IME。(请注意,如果您使用标准 API 进行输入,您的应用程序将会自动处理 IME。)通过启用 IME 支持,您的用户将可以输入象形文字,例如,从各种东亚书写系统输入。以下各节将探究 IME 的用途,并提供支持 IME 的最佳实际示例和技术解决方案。

IME 系统的工作方式

Windows 2000 和 Windows XP 中的 IME 模块适合于向应用程序传递用户输入信息的大型机制,而且像其他输入法一样,最简单、最安全的输入内容处理方式是使用标准系统控件,例如编辑字段和 Rich edit 控件等。如果您不是要编写 IME 软件包或自定义自己的 IME 用户界面 (UI),您可以使用标准输入 API,它可以为您处理 IME 的所有复杂情况。

对某种输入语言来说,是使用 IME 还是使用键盘来输入对用户而言都完全透明。无论用户是切换 IME 还是西方键盘布局,过程都完全相同。这两种操作都是通过单击任务栏上的语言指示符或输入某个快捷键组合来完成。而且,应用程序不关心使用的输入法,因为切换 IME 与切换键盘布局会生成同样的消息:WM_INPUTLANGCHANGEREQUEST(如果 IME 不是 TSF 的一部分)和 WM_INPUTLANGCHANGE。应用程序可通过调用 ActivateKeyboardLayout 来激活特定的 IME。IMM 可以作为中介来管理 IME 与应用程序之间的通信。当用户使用 IME 键入信息时,每个按键都发出一条带有 GCS_COMPSTR 标记的 WM_IME_COMPOSITION 消息,指出合成字符串有更新。消息的 WPARAM 值将返回字符串的第一个字符,其余字符可以通过带有相同 GCS_COMPSTR 标记的 ImmGetCompositionString API 进行检索。然后当用户按下 Enter 键或单击某个字符在文档中放置它时,默认情况下,IME 会发出一条带有 GCS_RESULTSTR 标记的 WM_IME_COMPOSITION 消息。(您可以使用相同的 API 和 GCS_RESULTSTR 标记来检索提交的字符串。)如果后面的 WM_IME_COMPOSITION 消息被发送到 DefWindowProc,则对于所提交字符串中的每个字符,它都会发出一条包含实际字符的 WM_IME_CHAR 消息。对于非 Unicode 窗口,如果 WM_IME_CHAR 消息包括一个双字节字符并且应用程序将此消息传递给 DefWindowProc,则 IME 会将此消息转换为两条 WM_CHAR 消息,每条包含双字节字符中的一个字节。如果应用程序略过任何一条消息,则它将由应用程序的 DefWindowProc 函数进行处理,此函数会通知 IMM 该消息被忽略。IME 然后会通过多个 WM_CHAR 消息逐字节重新发送字符或字符串。对于 Unicode 窗口,WM_IME_CHAR 和 WM_CHAR 是相同的。

以下各节将讨论对于 Windows 中所运行应用程序的三个离散的 IME 支持级别:不支持、部分支持和完全自定义的支持。应用程序可以小规模自定义 IME 支持(例如通过重新定位窗口),也可以彻底改变 IME UI 的外观。

无 IME 支持:不识别 IME 的应用程序通常会忽略所有特定于 IME 的 Windows 消息。大多数针对单字节语言的应用程序不能识别 IME。

不识别 IME 的应用程序会通过预定义的全局类(对应被称为 "IME")来继承活动 IME 的默认 UI。这一全局类具有与基于 Windows 的任何其他常用控件相同的特性。对于每个线程而言,Windows 2000 和 Windows XP 都会根据 IME 全局类自动创建一个窗口,所有不识别 IME 的线程窗口都会共用此默认的 IME 窗口。不识别 IME 的应用程序将关于 IME 的消息传递给 DefWindowProc 函数时,DefWindowProc 会将其发送到默认 IME 窗口。

部分 IME 支持:识别 IME 的应用程序可以创建其自己的 IME 窗口。部分支持 IME 的应用程序可以使用此应用程序 IME 窗口来控制特定的 IME 行为。例如,通过调用函数 ImmIsUIMessage,应用程序可以将与 IME 的 UI 相关的消息传递给应用程序的 IME 窗口,应用程序可以在这里处理这些消息。下列代码(包括适当的错误处理和可能更多已处理的消息)会出现在应用程序的 IME 窗口的窗口过程中:

HIMC hIMC;
LPVOID lpBufResult;
COMPOSITIONFORM cf;
DWORD dwBufLen;
if (ImmIsUIMessage(hIMEWnd, uMsg, wParam, lParam) == TRUE)
{
switch(uMsg)
{
case WM_IME_COMPOSITION:
if (lParam & GCS_RESULTSTR
{
hIMC = ImmGetContext(hWnd);
dwBufLen = ImmGetCompositionString(hIMC,
GCS_RESULTSTR, NULL, NULL) +
sizeof(TCHAR); lpBufResult =?malloc(dwBufLen); if(ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpBufResult, dwBufLen) > )
{
// ...
// process the text in lpBufResult
// ...
}
else // a negative error value was returned
{
// ...
// handle an error
// ...
} free(lpBufResult);
ImmReleaseContext(hWnd, hIMC);
}
break;
}
}
return ;
}

同样的窗口过程可能会调用 SendMessage 来重新配置状态、复合或候选窗口,或打开、关闭状态窗口。

SendMessage(hIMEWnd, WM_IME_CONTROL,
IMC_SETCOMPOSITIONWINDOW, "cf);

允许应用程序变更窗口位置或属性的其他 API 函数包括ImmSetCandidateWindow、ImmSetCompositionFont、ImmSet-CompositionString、ImmSetCompositionWindow 以及 ImmSetStatusWindowPos。包含部分 IME 支持的应用程序可使用这些函数来设置 IME UI 窗口的样式和位置,但是 IME 动态链接库 (DLL) 仍负责绘制这些窗口 – IME UI 的常规外观将保持不变。

完全 IME 支持则截然不同,完全识别 IME 的应用程序将接管通过 IME DLL 绘制 IME 窗口(状态、复合以及候选窗口)的工作。此类应用程序可以完全自定义这些窗口的外观,包括确定其屏幕位置以及选择使用哪些字体和字体样式来显示窗口中的字符。对于文字处理程序以及主要功能是文字处理的类似程序,这会使它们从流畅的 IME 交互以及创建“自然的”用户交互界面中受益,因此显得特别方便和有效。IME DLL 仍将决定在 IME 复合窗口和候选窗口中显示的字符,并且它还会运用算法来猜测字符并在 IME 字典中查找它们。FULLIME 是一个自定义 IME UI 的示例,可以在 Microsoft Windows Platform SDK 中找到它,网址为http://msdn.microsoft.com

完全识别 IME 的应用程序将通过下列方式捕获与 IME 相关的消息

  1. 它们调用 GetMessage 来检索中间 IME 消息。
  2. 它们在应用程序 WindowProc 中处理这些消息。
  3. 它们调用 TranslateMessage(IMM 的一部分)将消息传递到 IME DLL。像键盘驱动程序一样,IME 也需要同步静止键。请记住,如果使用标准输入调用(例如对 Rich Edit 控件的调用),部分 IME 支持可为您处理一切问题。

您已确信您的应用程序可以处理不同的输入语言和方法。确保您的应用程序可以支持多语言输入、输出以及显示的另一项任务是满足复杂脚本提出的固有要求。在随后的各节中,您将会看到与复杂脚本相关联的各种语言特点,并将了解到 Windows 对处理复杂脚本所提供的支持。

IME 编程相关的更多相关文章

  1. Linux环境编程相关的文章

    Linux环境编程相关的文章 好几年没有接触Linux环境下编程了,好多东西都有点生疏了.趁着现在有空打算把相关的一些技能重拾一下,顺手写一些相关的文章加深印象. 因为不是写书,也受到许多外部因素限制 ...

  2. Arduino使用注意问题及编程相关

    1.Arduino的概念 arduino是一款便捷灵活方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE), 是一个基于开放原始码的软硬件平台,构建于开放 ...

  3. 初探WINDOWS下IME编程

    初探WINDOWS下IME编程作者:广东南海市昭信科技有限公司-李建国 大家知道,DELPHI许多控件有IME属性.这么好用的东西VC可没自带,怎么办呢?其实,可通过注册表,用API实现.下面说一下本 ...

  4. 跨平台编程相关技术资料及笔记.md

    目录 跨平台编程技术选型 ## 需求 最终选定的技术方案:uni-app 混合或跨平台编程相关资料 ## uni-app 官网 相关资料 个人笔记 个人经验 ## taro 官网 相关资料 ## Ch ...

  5. Python网络编程相关的库与爬虫基础

    PythonWeb编程 ①相关的库:urlib.urlib2.requests python中自带urlib和urlib2,他们主要使用函数如下: urllib: urlib.urlopen() ur ...

  6. Python之路【第六篇】:面向对象编程相关

    判断类与对象关系 isinstance(obj, cls)  判断对象obj是否是由cls类创建的 #!/usr/bin/env python #-*- coding:utf-8 -*- class ...

  7. python 类编程相关内容(更新)

    python作为面向对象的编程语言,类和对象相关的编程当然是少不了的! python类: class 类名 : 变量名 [ = 初始值 ] …… def 函数名 ( self [ , 其余参数列表 ] ...

  8. php多进程编程相关资料(以备参考)

    进程与线程的区别 要了解二者的区别与联系,首先得对进程与线程有一个宏观上的了解. 进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位.每一个进程都 ...

  9. Spring AOP 面向切面编程相关注解

    Aspect Oriented Programming 面向切面编程   在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业.   ...

随机推荐

  1. [转载]poi导出excel,可以自定义保存路径

    poi导出excel比js导出excel安全性更好,在使用poi导出excel时,先要导入poi-3.5-FINAL-20090928.jar包到你项目的lib目录下,我这里选择是3.5版的 1.ac ...

  2. multiple backgrounds

    multiple backgrounds 多重背景,也就是CSS2里background的属性外加origin.clip和size组成的新background的多次叠加,缩写时为用逗号隔开的每组值:用 ...

  3. cacti手册选译(1)

    第一章 系统需求 Cacti需要你的系统安装一下软件: RRDTool版本1.0.49及以上,推荐1.4+ MYSQL5.x及以上版本 PHP5.1及以上 支持PHP的web Server如Apach ...

  4. 【笔记】ASP.NET MVC Model元数据

    问题1:什么叫Model元数据? Model元数据,是针对数据类型的一种描述信息.由于复杂类型(或者说类型嵌套的存在,比如CustomerModel中有一个属性为复杂类型Address)的存在,因此M ...

  5. 用PHP对数据库数据进行删除

    显示页面: <body> <table width="100%" border="1" cellpadding="0" c ...

  6. CSS3动画制作的简单示例

    CSS3 大大强化了制作动画的能力,但是如果要做出图案比较复杂的动画,选择 GIF 依然是一个不错的选择.今天给大家介绍一个使用 CSS animation 配合雪碧图(CSS sprite)来制作动 ...

  7. 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉

    DP/单调队列优化 首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $  当然这里的$i$和$k$都是偶数啦~ ...

  8. js 调用IE内置打印控件

    转自学网(http://www.xue5.com/itedu/200802/102909.html) WebBrowser是IE内置的浏览器控件,无需用户下载. 一.WebBrowser控件 < ...

  9. 在当前iframe中, 获取Iframe的id

    window.frameElement   返回嵌入当前window对象的元素(比如 <iframe> 或者 <object>),如果当前window对象已经是顶层窗口,则返回 ...

  10. HDOJ 1466 计算直线的交点数

    将n 条直线排成一个序列,直线2和直线1最多只有一个交点,直线3和直线1,2最多有两个交点,......,直线n 和其他n-1条直线最多有n-1个交点.由此得出n条直线互不平行且无三线共点的最多交点数 ...