这些指南和要求可以帮助你开发自定义输入法编辑器(IME),从而协助用户输入在标准 QWERTY 键盘上难以方便表示的语言文本。
有关 IME 的概述,请参阅输入法编辑器(IME)。
默认 IME
用户可以选择任何活动 IME(设置 -> 时间 - 语言 - 语言 ->> 首选语言 -> 语言包 - 选项) 作为其首选语言的默认 IME。
在语言选项设置屏幕上为首选语言选择默认键盘。
重要
不建议直接写入注册表,以便为自定义 IME 设置默认键盘。
兼容性要求
以下是自定义 IME 的基本兼容性要求。
IME 必须与 Windows 应用兼容
使用 文本服务框架 (TSF) 实现 IME。 以前,可以选择将 输入法管理器(IMM32) 用于输入服务。 现在,系统会阻止使用输入法管理器(IMM32)实现的 IME。
应用启动时,TSF 会为用户当前选择的 IME 加载 IME DLL。 加载 IME 时,它受到与应用相同的应用容器限制。 例如,如果应用在其清单中未请求 Internet 访问,则 IME 无法访问 Internet。 此行为可确保 IME 不能违反安全协定。
TSF 是应用与 IME 之间的中介。 TSF 将输入事件传达给 IME,并在用户选择字符后从 IME 接收输入字符。
此行为与以前版本的 Windows 相同,但加载到 Windows 应用中会影响 IME 的潜在功能。
如果你的 IME 需要在 Windows 应用和桌面应用之间提供不同的功能或 UI,请确保 TSF 加载的 DLL 会检查要加载到的应用类型。 在 IME 中调用 ITfThreadMgrEx::GetActiveFlags 方法并检查TF_TMF_IMMERSIVEMODE标志,因此 IME 会根据结果触发不同的应用程序逻辑。
Windows 应用不支持表文本服务 (TTS) IME。
注释
一些用于生成 TTS IME 的工具生成由 Windows 标记为恶意软件的 IME。
IME 必须与系统托盘兼容
没有用于托管 IME 图标的语言栏。 而是在系统托盘上显示一个指示当前输入选项的输入指示器。 输入指示器仅显示 IME 品牌图标以指示当前正在运行的 IME。 此外,还有一个 IME 模式图标,它显示在 IME 品牌图标的左侧,供用户执行最常用的 IME 模式开关,例如打开或关闭 IME。
输入指示器仅针对兼容的 IME 显示 IME 品牌标识和模式标识。 不兼容的 IME 没有系统托盘中显示的品牌图标和模式图标。 相反,输入指示器显示语言缩写而不是 IME 品牌图标。
将 IME 图标存储在 DLL 或 EXE 文件中,而不是独立的.ico文件。 IME 图标的设计必须遵循以下 UI 设计指南部分中所述的准则。
IME 品牌图标
输入指示使用 IME 在系统上注册时定义的资源 ID,从 IME DLL 获取 IME 品牌图标。
IME 模式图标
某些 IME 可能需要依赖系统托盘上显示的输入指示器来显示 IME 模式图标。 在这种情况下,IME 使用 GUID_LBI_INPUTMODE 将 IME 模式图标传递到输入指示器。
将 IME 模式图标传递到系统托盘上的输入指示器时,IME 模式图标的默认大小为 16x16 像素。 UI 缩放遵循 DPI。
将 IME 模式图标传递给 UAC 上的输入指示器(安全桌面中的用户帐户控制),IME 模式图标的默认大小为 20x20 像素。 UAC 上 IME 模式图标的 UI 缩放遵循 PPI。
IME 必须在应用容器中工作
某些 IME 函数在应用容器中受到影响。
- 字典文件 - 通常,IME 具有只读字典文件,用于将用户输入映射到特定字符。 若要从应用容器内部访问这些文件,IME 必须将这些文件放置在 Program Files 或 Windows 目录下。 默认情况下,可以从应用容器读取这些目录,因此 IME 可以访问存储在这些位置的字典文件。 如果 IME 必须将字典文件存储在其他位置,则必须显式管理字典文件的 访问控制列表(ACL),以便允许应用容器进行访问。
- Internet 更新 - 如果你的 IME 需要使用来自 Internet 的数据更新其字典,则它无法可靠地在应用容器内执行此作,因为 Internet 访问并不总是允许的。 相反,IME 应运行单独的桌面进程,该进程负责使用 Internet 中的数据更新字典文件。
- 即时学习 - 如果 IME 在具有 Internet 访问权限的应用容器中运行,则 IME 可以与之通信的终结点没有限制。 在这种情况下,IME 可以使用云服务器提供实时学习服务。 某些输入法在用户键入时会即时下载并上传用户的输入内容。 由于在应用容器中不能保证 Internet 访问,因此可能始终不允许这样做。
- 在进程之间共享信息 - IME 可能需要在不同应用容器中的应用之间共享有关用户输入首选项的数据。 使用 Web 服务在应用之间共享数据。
重要
如果尝试规避应用容器安全规则,则 IME 可能被视为恶意软件并被阻止。
IME 和触摸键盘
IME 必须确保其候选窗格的 UI 和其他 UI 元素不会绘制在触摸键盘之下。 触摸键盘显示在高于所有应用的 Z 顺序带区中,且 IME UI 显示在与可使用此 IME UI 的应用相同的 Z 顺序带区中。 因此,触摸键盘可以重叠并隐藏 IME UI。 在大多数情况下,应用应调整其窗口的大小,以考虑触摸键盘。 如果应用大小不调整,IME 仍可使用 InputPane API 获取触摸键盘的位置。 IME 查询 Location 属性,或者为触摸键盘的“显示”和“隐藏”事件注册处理程序。 用户每次点击编辑字段时,即使当前已显示触摸键盘,仍会引发 Show 事件。 IME 绘制候选 UI 或其他 UI 之前,可以使用此 API 获取触摸键盘使用的屏幕空间,并重新排列 IME UI 以避免其绘制在触摸键盘之下。
指定首选触摸键盘布局
IME 可以指定要使用的触摸键盘布局,并且 IME 可用于触摸优化布局。 此功能仅限于朝鲜语、日语、简体中文和繁体中文输入语言的 IME。
触摸键盘支持七种布局,其中三种是经典布局,其中四种是触摸优化布局。 经典布局的外观和行为类似于物理键盘。
这三种经典布局都用于以不同形式输入繁体中文:
- 基于拼音的输入
- 仓颉输入
- 大易输入
除了经典布局,每个朝鲜语、日语、简体中文和繁体中文输入语言都有一个触摸优化布局。
若要使用此功能,IME 必须实现 ITfFnGetPreferredTouchKeyboardLayout 接口,该接口由 IME 使用文本服务框架 ITfFunctionProvider API 导出。
如果 IME 不支持 ITfFnGetPreferredTouchKeyboardLayout 接口,则使用 IME 会导致触摸键盘显示的语言的默认经典布局。
如果你的 IME 需要将其中一个经典布局设置为首选布局,则除了支持 ITfFnGetPreferredTouchKeyboardLayout 和 ITfFunctionProvider 接口之外,IME 端不需要其他工作。 但是,IME 中需要执行其他工作才能使用触摸优化布局,下一部分对此进行介绍。
触摸优化布局
韩语、日语、简体中文和繁体中文输入语言的触摸优化键盘在 IME 开启和关闭模式下显示不同的布局。 触摸键盘上有一个键可将 IME 转换模式设置为“开”或“关”,但键盘的 IME 模式也可能随着编辑控件中的焦点更改而更改。
日语、简体中文和繁体中文输入语言的触摸优化键盘配有一个或多个按键,IME 使用这些按键来浏览候选页面。 对于日语和简体中文,候选页键显示在触控优化布局上。 对于繁体中文,上一个和下一个候选页面分别有独立的键。
按下这些键时,触摸键盘会调用 SendInput 函数以将以下 Unicode 专用区域字符发送到焦点应用程序,IME 会截获这些字符并对其进行处理:
- 下一页(0xF003) - 当候选页面键按下日语和简体中文的触摸优化键盘上时发送,或者下一页键在传统中文的触摸优化键盘上按下时发送。
- 上一页(0xF004) - 当候选页面键与日语和简体中文的触摸优化键盘上的 Shift 键同时按下时发送,或者在传统中文的触摸优化键盘上按下上一页键时发送。
这些字符作为 Unicode 输入发送。 下一段详细介绍了如何在密钥事件接收器通知期间提取文本服务框架 IME 将接收的字符信息。 这些字符值未在任何头文件中定义,因此需要在代码中定义它们。
若要截获键盘输入,IME 必须注册为键事件接收器。 对于使用 SendInput 函数生成的 Unicode 输入, ITfKeyEventSink 回调(OnKeyDown 、OnKeyUp、OnTestKeyDown、OnTestKeyUp)的 WPARAM 参数始终包含虚拟密钥VK_PACKET,并且不直接标识字符。
实现以下调用序列以访问字符:
// Keyboard state
BYTE abKbdState[256];
if (!GetKeyboardState(abKbdState))
{
return 0;
}
// Map virtual key to character code
WCHAR wch;
if (ToUnicode(VK_PACKET, 0, abKbdState, &wch, 1, 0) == 1)
{
return wch;
}
IME 搜索集成
通过搜索协定为用户提供搜索功能,并与搜索窗格集成。
搜索窗格和 IME 建议
搜索窗格是用户跨所有应用执行搜索的中心位置。 对于 IME 用户,Windows 提供独特的搜索体验,使兼容的 IME 与 Windows 集成,以提高效率和可用性。
使用与搜索兼容的 IME 键入的用户将获得两个主要优势:
- IME 与搜索体验之间的无缝交互。 IME 候选项直接显示在搜索框下,而不会遮挡搜索建议。 用户可以使用键盘在搜索框、IME 转换候选项和搜索建议之间无缝导航。
- 更快地访问应用程序提供的相关结果和建议。 该应用有权访问所有当前转化候选对象,以提供更相关的建议。 为了更好地确定搜索建议的优先顺序,按相关性顺序向应用程序提供转换。 用户只需键入拼音即可找到并选择所需的结果,而无需转换。
如果 IME 符合以下条件,则 IME 与集成搜索体验兼容:
- 兼容 Windows 样式界面。
- 实现 TSF 无 UI 模式 API。 有关详细信息,请参阅 无 UI 模式概述。
- 实现 TSF 搜索集成 API、 ITfFnSearchCandidateProvider 和 ITfIntegratableCandidateListUIElement。
在搜索窗格中激活时,兼容的 IME 将置于 UIless 模式下,并且无法显示其 UI。 相反,它会将转换候选项发送到 Windows,从而在内联候选项列表控件中显示,如上一个屏幕截图所示。
此外,IME 发送用于运行当前搜索的候选词。 这些候选项可以与转换候选项相同,也可以针对搜索进行定制。
优质搜索候选项符合以下条件:
- 无前缀重叠。 例如,“北京大学”和“北京”是冗余的,因为前者包含后者,构成了前缀关系。
- 没有多余的候选项。 任何冗余候选项对搜索没有用,因为它没有助于筛选结果。 例如,与北京大学匹配的任何结果也与北京匹配。
- 无预测候选项(只能转换)。 例如,如果用户键入“be”,IME 能返回候选项“北”,但不能返回“北京大学”。 通常,预测候选项太具有限制性。
不符合条件的 IME 无法像其他控件那样与搜索显示兼容,因此不能利用 UI 集成和搜索候选项。 应用仅在用户完成撰写后接收查询。
当支持搜索协定的应用收到查询时,查询事件将包含包含所有已知替代项的“queryTextAlternatives”数组,从最相关的(可能)到最不相关的(不太可能)。
提供替代项时,应用应将每个替代项视为查询,并返回与任何替代项匹配的所有结果。 应用的行为应与用户同时发出多个查询一样,实质上是向提供结果的服务发出“或”查询。 出于性能考虑,应用通常会将匹配限制为 5 到 20 个最相关的替代项。
UI 设计指南
所有 IME 都必须遵循 设计和代码 Windows 应用中所述的用户体验准则。
不要使用粘滞窗口
IME 窗口应仅在需要时显示,并且不应一直可见。 当用户不需要键入时,IME 窗口不应显示。 IME 窗口不应是全屏窗口。 IME 窗口不应相互重叠。 窗口应采用 Windows 样式设计,并遵循 UI 缩放。
IME 图标
有两种类型的 IME 图标,品牌图标和模式图标。 所有 IME 图标都必须仅使用黑白颜色进行设计。 新的 IME 图标借用系统托盘图标的字形外观。 此样式的创建旨在让所有语言都能使用它来增强整体统一风格的亲和感,同时又能相互区分出各自的特点。
IME 图标的文件格式为 ICO。 必须提供以下图标大小。
- 16x16 像素
- 20x20 像素
- 24x24 像素
- 32x32 像素
- 40x40 像素
- 48x48 像素
确保所有分辨率中都提供了具有 alpha 通道的 32 位图标。
IME 品牌图标通过一个白色框及其中放置的一个以现代字样呈现的印刷字形来定义。 每个语言团队都选择了自己的定义字形。 字形为黑色。 框的外边框为 1 像素大小,黑色且不透明度为 50%。 “新建”版本由框左上角的圆角定义。
IME 模式图标通过一个采用现代字样的白色印刷字形及大小为 1 像素、不透明度为 50% 的黑色外边框来定义。
| 图标 | Description |
|---|---|
|
|
繁体中文仓颉 IME 品牌图标示例。 |
|
|
繁体中文仓颉 IME 品牌图标示例。 |
|
|
示例 IME 模式图标。 |
拥有的窗口
若要显示候选 UI,IME 必须将其窗口设置为拥有的窗口,以便在当前正在运行的应用上显示。 使用 ITfContextView::GetWnd 方法检索要拥有的窗口。 如果 GetWnd 返回错误或 NULLHWND,请调用 GetFocus 函数。
if (FAILED(pView->GetWnd(&parentWndHandle)) || (parentWndHandle == nullptr)) { parentWndHandle = GetFocus(); }
通过轻型消除表面与 IME 候选窗口交互
弹出窗口的关闭方式称为“轻松关闭”,因为用户很容易关闭这种窗口。 若要使 IME 在 Windows 交互模型中正常运行,IME 窗口必须参与光消除模型。
为采用轻型消除模型,IME 必须使用 NotifyWinEvent 函数或类似函数引发三个新的 Windows 事件。 这些新事件包括:
- EVENT_OBJECT_IME_SHOW - 当 IME 变为可见时引发此事件。
- EVENT_OBJECT_IME_HIDE - 隐藏 IME 时引发此事件。
- EVENT_OBJECT_IME_CHANGE - IME 移动或更改大小时引发此事件。
声明兼容性
IME 使用 ITfCategoryMgr::RegisterCategory 注册 GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT 类别,以此声明其兼容性。
将默认 IME 模式设置为“打开”
我们为 IME 提供更好的 UX。
桌面应用程序的 DPI 缩放支持
增强的 DPI 缩放支持允许查询每个桌面进程的声明的 DPI 感知级别,以确定它是否需要缩放 UI。 在多监视器方案中,Windows 针对每个监视器上的不同 DPI 设置相应地缩放 UI。
由于 IME 在每个应用程序进程的上下文中运行,因此不应为 IME 声明 DPI 感知级别。 这可确保 IME 在当前进程的 DPI 感知级别运行。
若要确保所有 IME UI 元素的缩放与运行进程的 UI 元素一致,必须适当调整以匹配不同的 DPI 值。
注释
为了确保与新的桌面应用程序保持一致性,您的 IME 应支持每个显示器的 DPI 感知,但不应自行声明感知级别。 系统确定每个方案中的相应缩放要求。
有关桌面应用程序的 DPI 缩放支持要求的详细信息,请参阅 高 DPI。
IME 安装
如果使用 Microsoft Visual Studio 生成 IME,请使用第三方安装程序(如 Flexera Software 中的 InstallShield)为 IME 创建安装体验。
以下步骤演示如何使用 InstallShield 为 IME DLL 创建安装项目。
- 安装 Visual Studio。
- 启动 Visual Studio。
- 在 “文件 ”菜单上,指向“ 新建 ”并选择“ 项目”。 此时会打开 “新建项目 ”对话框。
- 在左窗格中,导航到 “模板 > 其他项目类型 > 设置和部署”,单击“ 启用 InstallShield Limited Edition”,然后单击“ 确定”。 按照安装说明进行操作。
- 重启 Visual Studio。
- 打开 IME 解决方案(.sln)文件。
- 在解决方案资源管理器中,右键单击解决方案,指向 “添加”,然后选择“ 新建项目”。 此时会打开“ 添加新项目 ”对话框。
- 在左侧树视图控件中,导航到 “模板 > 其他项目类型 > InstallShield Limited Edition”。
- 在中心窗口中,单击 InstallShield Limited Edition 项目。
- 在“ 名称 ”文本框中,键入“SetupIME”,然后单击“ 确定”。
- 在 “项目助手 ”对话框中,单击“ 应用程序信息”。
- 请填写您的公司名称和其他信息。
- 单击 “应用程序文件”。
- 在左窗格中,右键单击 [INSTALLDIR] 文件夹,然后选择“ 新建文件夹”。 将文件夹命名为“Plugins”。
- 单击“ 添加文件”。 导航到 IME DLL 并将其添加到 插件 文件夹。 对 IME 字典重复此步骤。
- 右键单击 IME DLL 并选择 “属性”。 此时将打开“属性”对话框。
- 在 “属性 ”对话框中,单击 “COM 和 .NET 设置 ”选项卡。
- 在 “注册类型”下,选择 “自我注册 ”,然后单击“ 确定”。
- 生成解决方案。 IME DLL 已构建完成,InstallShield 创建了一个 setup.exe 文件,使用户能够在 Windows 上安装你的 IME。
若要创建自己的安装体验,请调用 ITfInputProcessorProfileMgr::RegisterProfile 方法,在安装过程中注册 IME。 不要直接写入注册表项。
如果在安装后必须立即使用 IME,请调用 InstallLayoutOrTip ,将 IME 添加到启用用户的输入法,并使用以下 psz 参数格式:
<LangID 1>:{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
IME 辅助功能
实现以下约定,使 IME 符合可访问性要求,并使用“讲述人”。 若要使候选列表易于访问,IME 必须遵循此约定。
- 候选列表的 UIA_AutomationIdPropertyId 必须等于转换候选项列表的“IME_Candidate_Window”或预测候选列表的“IME_Prediction_Window”。
- 当候选列表出现和消失时,它会分别引发UIA_MenuOpenedEventId和UIA_MenuClosedEventId类型的事件。
- 当当前所选候选项发生更改时,候选列表将引发 UIA_SelectionItem_ElementSelectedEventId。 所选元素的属性 UIA_SelectionItemIsSelectedPropertyId 等于 TRUE。
- 候选列表中的每个项目的 UIA_NamePropertyId 必须是候选项的名称。 (可选)可以通过 UIA_HelpTextPropertyId提供其他信息来消除候选人的歧义。