中文信息处理技术专栏

中文信息处理技术专栏


首页  中文信息处理技术专栏

  • TSF(Text Services Framework)和输入法
  • 时间: 2017-07-25    阅读数: 10
  • 1.TSF输入接口

    IMM-IME架构成熟,稳定,易于实现,在Windows中被广泛使用,甚至在Linux曾大量使用的中文输入接口SCIM中也可以看到IMM-IME的影子。但是由于IMM-IME在操作权限管理上有些欠缺,输入法文件的扩展名是IME,但是实质是DLL,使得恶意软件通过该接口挂接到应用程序成为可能。为了提高安全性、规范性,Microsoft设计了基于COMComponent Object Model)的TSFText Services Framework)接口。

    TSF是文本服务框架的简称,基于TSF的每一个输入法IME都是COM组件。图1显示了TSF与应用程序之间的关系, TSF管理器由操作系统提供并且不可被替换,它是应用程序和IME之间的中介。基于安全的考虑,IME也不能直接和应用程序打交道,TSF将输入事件传达给IME并在用户选择字符后接受从 IME 返回的输入字符。与IMM-IME类似,TSF中的IME同样可以由第三方开发。

    Windows 8/8.110开始提供了Metro界面和传统桌面两种工作模式,在传统桌面的工作模式中同时支持IMM-IMETSF两种架构,但在Metro界面中就只支持TSF架构的输入法了,因此基于TSF的输入法必将淘汰IMM-IME结构的输入法。

    支持TSF的应用程序可以在不用感知文本设备的前提下,接受从不同文本设备(键盘、手写、语音等)来源的文本输入。此外,TSF的一个重要优势是对输入法权限的管控程度远远高于IMM-IME,大大有利于系统的安全性。

    1 TSF架构

    2.COM Component Object Class

    COM提供了一种在不同的应用程序和语言之间共享二进制代码的规范,COM本身的设计是和具体程序设计语言无关,因此不依赖任何语言层面的特征。使用COM编写的二进制模块必须适应与支持一些特定的数据结构,COM规范同样也定义COM对象在内存中应该如何被组织与安排。

    COM基本术语

    1)接口interface:接口可以看成是包含一组待实现方法的类。接口名通常以I开头,在C++中,接口就是包含纯虚函数的抽象类。

    2)组件对象类coclass:它的全称是component object classcoclass用来实现接口。一个COM对象是coclass类在内存中的一个实例。

    3) 组件服务器COM Server:含有一个或多个coclass的二进制模块,可以是DLL文件也可以是EXE文件。

    4Registration:向Windows注册、登记COM Server的位置和入口。

    5Unregistration:是Registration的逆过程,从Windows中移除掉这个登记。

    6GUID:它的全称是globally unique identifier,是一个128位的无符号数,用于唯一标记接口和组件对象类,有时GUID也被称为UUIDuniversally unique identifier)。一个coclassclass ID称为CLSID;一个interfaceinterfaceID称为IID

    基接口(base interface):IUnknown

    每一个COM接口都要从IUnknown接口继承,IUnknown接口提供了两个非常重要的特性:生存期控制和接口查询。IUnknown接口是所有COM接口的根。该接口用C++描述如下:

    class IUnknow

    {

    public:

          virtual  HRESULT    _stdcall Queryface(const IID& iid,void **ppv) = 0;

          virtual  ULONG       _stdcall AddRef() = 0;

          virtual  ULONG       _stdcall  Release() = 0;

    };

    可见这个接口有三个方法: QueryInterfaceAddRefReleaseQueryInterface用于在获取某个COM的一个接口指针后,查询该COM的其它接口指针。AddRef用于增加引用计数,Release用于减少引用计数。

    3.物理键盘与软键盘

    由于Windows 8/10的手持设备通常没有物理键盘,因此触控键盘成为了TSF输入法必要组成部分。Windows 8TSF触摸键盘支持七种布局,其中三种属于经典布局,四种属于触摸优化布局。经典布局的外观和行为和物理键盘更加相似,四种优化布局是分别针对朝鲜语、日语、简体中文和繁体中文而设计的。图2就是在简体中文优化布局下的数字触控键盘。

    2 简体中文优化布局下的数字触控键盘

    ITfFnGetPreferredTouchKeyboardLayou接口的函数GetLayout是一个虚函数,可以通过重写该函数实现为TSF输入法指定触控键盘布局,但是TSF不允许用户自定义自己的触控键盘布局。表1列出了GetLayout指定触控键盘的参数,具体细节可以到MSDN中查询。

    1 七种触控键盘布局

    布局定义

    语系

    TKBL_CLASSIC_TRADITIONAL_CHINESE_PHONETIC

    0x0404

    CHT

    TKBL_CLASSIC_TRADITIONAL_CHINESE_CHANGJIE

    0xF042

    CHT

    TKBL_CLASSIC_TRADITIONAL_CHINESE_DAYI

    0xF043

    CHT

    TKBL_OPT_JAPANESE_ABC

    0x0411

    JPN

    TKBL_OPT_KOREAN_HANGUL_2_BULSIK

    0x0412

    KOR

    TKBL_OPT_SIMPLIFIED_CHINESE_PINYIN

    0x0804

    CHS

    TKBL_OPT_TRADITIONAL_CHINESE_PHONETIC

    0x0404

    CHT

    实验原理

    4.TSF输入接口

    TSF设计了十余个接口,表2中列出了最主要的输入接口,编写TSF的输入法需要继承并实现这些接口。

    62 TSF输入法接口

    接口

    说明

    ITfTextInputProcessorEx

    TSF管理器通过该接口激活或冻结输入法。

    ITfThreadMgrEventSink

    用于接收线程管理器的事件通知。

    ITfKeyEventSink

    输入法用来接收和拦截键盘与焦点通知。

    ITfCompositionSink

    处理输入码编辑被终止的情况。

    ITfDisplayAttributeProvider

    TSF管理器通过该接口获取独立显示对象

    ITfActiveLanguage-
       ProfileNotifySink

    输入法被选择。

    ITfThreadFocusSink

    线程获取或者失去焦点

    ITfFunctionProvider

    用于枚举提供的函数对象。

    ITfFnGetPreferredTouch-
       KeyboardLayout

    用于选择输入法所要使用的虚拟键盘的布局。

    ITfTextEditSink

    支持实现包含读写权限的编辑Session

    TSF输入法的类需要继承上述的接口,并对接口中的必要函数进行定制与实现。下面对其中最重要的ITfKeyEventSink进行简要介绍,表3列出了该接口的主要函数以及说明。

    3 ITfKeyEventSink接口的函数说明

    函数

    函数说明

    OnSetFocus

    当输入法得到或者失去键盘焦点时自动调用

    OnPreservedKey

    当发生系统保留键事件。

    OnTestKeyDown 

    当一个键盘KeyDown事件发生时,调用本函数来判断输入法是否需要一个按键。

    OnKeyDown

    如果OnTestKeyDown   认为需要,则调用本函数。

    OnTestKeyUp

    OnTestKeyDown类似

    OnKeyUp

    OnKeyDown类似

    值得说明的是:虽然一次按键会发生KeyDownKeyUp消息,但是输入法通常只要选择处理其中一类消息。例如纵横输入法就是重点实现了OnTestKeyDownOnKeyDown两个函数。不同的输入法运行机制类似,但是对于按键的处理各有不同,因此每种输入法都需要对这两个函数深度定制。

    5.TSF输入法部署

    目前,64位的计算机已经成为主流,但是为了和32位的程序兼容,Windows 8/10 X64中也允许安装与运行32位程序。为了保证用户能够便捷地在不同程序中使用输入法,因此需要编译输入法的X64X86的两个版本并发布到用户计算机中,因为64位的应用程序只能使用64位的输入法,32位的程序必须使用32位的输入法。

    64位的输入法可以部署到用户计算机的Windows安装文件夹下的System32子文件夹,32位的版本部署到Windows安装文件夹下的SysWOW64子文件夹。

    6.TSF输入法注册

    由于TSF的输入法是一个COM组件,因此注册的方法和COM组件一样,实质是在注册表HKEY_CLASSES_ROOT中建立类似如下的键:

    [HKEY_CLASSES_ROOT\CLSID\{D2291A80-84D8-4641-9AB2-BDD1472C846B}]

    @=纵横汉字输入法

    [HKEY_CLASSES_ROOT\CLSID\{D2291A80-84D8-4641-9AB2-BDD1472C846B}\InProcServer32]

    @=C:\\WINDOWS\\system32\\CKCIme.dll

    ThreadingModel=Apartment

    {D2291A80-84D8-4641-9AB2-BDD1472C846B}是一个用于区分COM组件的全球唯一ID,开发人员可以根据需要自己需要定制与修改。

    32位版本的输入法在注册表注册信息如下:

    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{D2291A80-84D8-4641-9AB2-BDD1472C846B}]

    @=纵横汉字输入法

    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{D2291A80-84D8-4641-9AB2-BDD1472C846B}\InProcServer32]

    @=C:\\WINDOWS\\SysWow64\\CKCIme.dll

    ThreadingModel=Apartment

    但是Microsoft不建议用户直接写注册表注册输入法,而是希望大家通过调用系统提供的ITfInputProcessorProfileMgrRegisterProfile方法进行注册,该方法原型如下:

    HRESULT RegisterProfile(

      REFCLSID rclsid,     //输入法服务的唯一CLSID

      LANGID   langid,   //语系ID

      REFGUID  guidProfile,

      const WCHAR    *pchDesc,

      ULONG    cchDesc,

      const WCHAR    *pchIconFile, //图标文件名

      ULONG    cchFile,

      ULONG    uIconIndex,  //图标索引号

      HKL      hklSubstitute,

      DWORD    dwPreferredLayout,    //未使用,必须填0

      BOOL     bEnabledByDefault,

      DWORD    dwFlags

    );

    7.输入法的权限问题

    这里的权限主要包括网络权限和文件系统访问权限。TSF输入法的权限取决于使用它的用户以及应用程序,在应用启动的时候,TSF为用户当前选择的IME加载COM组件。当IME加载到Windows应用商店应用时,它受与该应用相同的权限限制。例如:如果使用TSF输入法的应用程序不具有Internet访问权,则TSF输入法也不可以访问 Internet。因此一些IMM-IME输入法的自动通过网络升级码本数据的功能在TSF中需要重新设计。

    另外大多数输入法都需要使用码本文件,码本存储了一个输入法的输入码和机内码对应关系。桌面应用程序通常对文件系统的访问权限相对高,而基于应用商店的应用对计算机文件系统的访问权限非常有限,因此为了保证码本文件总能被合法访问,建议存储到系统的“Program Files”文件夹中的子文件夹。IMM-IME输入法经常提供的在输入时自动或者手动为用户添加自定义词组的功能因为需要写文件权限,在TSF中也可能会失败。


地址:苏州市十梓街1号 苏州大学纵横研究所联系电话:0512-65243192电子邮箱:ckc@suda.edu.cn

Copyright © 苏州大学纵横汉字信息技术研究所 2017