原文 C# TSF 输入法的获取

起因:

「添雨跟打器」中存在一个问题。在 windows 8/10 里面,输入法就获取不到了。我一直没有去管这样的问题。但是也大致知道,可能是 TSF 架构的问题。

TSF:

Microsoft Windows 文本服务框架(TSF) 是一个包含在Windows XP 及其后继版本操作系统的系统服务。TSF为高级文本输入的通信以及自然语言技术提供了一个简单的可扩展的框架。

以上引自百度百科。

MSDN:

于是第一时间去 MSDN 查看了一下关于 TSF 。全英文的文档看得云里雾里。但是搞清了一点情况。TSF 它在 Windows 里面所对应的 dll 文件——msctf.dll

使用 Visual Studio 自带的命令工具查看该 dll 的函数列表如下:

命令:

1
dumpbin -exports msctf.dll

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

Dump of file msctf.dll
File Type: DLL
  Section contains the following exports for MSCTF.dll
    00000000 characteristics
    5699C6A2 time date stamp Sat Jan 16 12:27:14 2016
        0.00 version
           1 ordinal base
          73 number of functions
          73 number of names
    ordinal hint RVA      name
          2    0 000183E0 CtfImeAssociateFocus
          3    1 000633E0 CtfImeConfigure
          4    2 00046A10 CtfImeConversionList
          5    3 000042E0 CtfImeCreateInputContext
          6    4 0000BF70 CtfImeCreateThreadMgr
          7    5 000633F0 CtfImeDestroy
          8    6 00038C40 CtfImeDestroyInputContext
          9    7 00038840 CtfImeDestroyThreadMgr
         10    8 00037D40 CtfImeDispatchDefImeMessage
         11    9 00046A10 CtfImeEnumRegisterWord
         12    A 00046A10 CtfImeEscape
         13    B 00063410 CtfImeEscapeEx
         14    C 00063490 CtfImeGetGuidAtom
         15    D 00046A10 CtfImeGetRegisterWordStyle
         16    E 00046A10 CtfImeInquire
         17    F 00006E60 CtfImeInquireExW
         18   10 000634F0 CtfImeIsGuidMapEnable
         19   11 00063540 CtfImeIsIME
         20   12 0001C540 CtfImeProcessCicHotkey
         21   13 00018840 CtfImeProcessKey
         22   14 00046A10 CtfImeRegisterWord
         23   15 00046A10 CtfImeSelect
         24   16 00036CC0 CtfImeSelectEx
         25   17 000184A0 CtfImeSetActiveContext
         26   18 000635C0 CtfImeSetCompositionString
         27   19 000635D0 CtfImeSetFocus
         28   1A 00063640 CtfImeToAsciiEx
         29   1B 00046A10 CtfImeUnregisterWord
         30   1C 00004A10 CtfNotifyIME
         31   1D 000049F0 DllCanUnloadNow
         32   1E 000018C0 DllGetClassObject
         33   1F 00061430 DllRegisterServer
         34   20 00061780 DllUnregisterServer
         35   21 0003FDD0 SetInputScope
         36   22 0008A580 SetInputScopeXML
         37   23 0003FE50 SetInputScopes
         38   24 0003FEA0 SetInputScopes2
         39   25 00063650 TF_CUASAppFix
         40   26 000056B0 TF_CanUninitialize
         41   27 00046540 TF_CleanUpPrivateMessages
         42   28 0003E5E0 TF_CreateCategoryMgr
         43   29 00002BB0 TF_CreateCicLoadMutex
         44   2A 000028E0 TF_CreateCicLoadWinStaMutex
         45   2B 00063690 TF_CreateDisplayAttributeMgr
         46   2C 000047F0 TF_CreateInputProcessorProfiles
         47   2D 000636B0 TF_CreateLangBarItemMgr
         48   2E 000396B0 TF_CreateLangBarMgr
         49   2F 000636D0 TF_CreateThreadMgr
         50   30 0000B110 TF_GetAppCompatFlags
         51   31 000636F0 TF_GetCompatibleKeyboardLayout
         52   32 0003EE90 TF_GetGlobalCompartment
         53   33 0006A6F0 TF_GetInitSystemFlags
         54   34 0003A7F0 TF_GetInputScope
         55   35 0008E580 TF_GetShowFloatingStatus
         56   36 00005410 TF_GetThreadFlags
         57   37 0000D5C0 TF_GetThreadMgr
         58   38 00002DB0 TF_InitSystem
         59   39 00046A10 TF_InvalidAssemblyListCacheIfExist
         60   3A 0006F4F0 TF_IsCtfmonRunning
         61   3B 00063880 TF_IsLanguageBarEnabled
         62   3C 00046A10 TF_IsThreadWithFlags
         63   3D 00063980 TF_MapCompatibleHKL
         64   3E 00063A10 TF_MapCompatibleKeyboardTip
         65   3F 000191B0 TF_Notify
         66   40 00005E90 TF_PostAllThreadMsg
          1   41 00063330 TF_RunInputCPL
         67   42 00063A20 TF_SendLangBandMsg
         68   43 00040550 TF_SetDefaultRemoteKeyboardLayout
         69   44 0008E590 TF_SetShowFloatingStatus
         70   45 00046A10 TF_SetThreadFlags
         71   46 00002D10 TF_UninitSystem
         72   47 00002C50 TF_WaitForInitialized
         73   48 000AA2E0 TextInputClientWrapperCreate
  Summary
        3000 .data
        1000 .didat
        D000 .pdata
       25000 .rdata
        2000 .reloc
       42000 .rsrc
       DF000 .text

百度:

继续百度搜索一翻。关键字:C#TextServiceFramework。第一篇《微软新一代输入法框架 TSF – Text Service Framework 小小的研究》,跳转至这篇博文时,则找到真正需要的东西。

Wrapper:

《VISTA 與輸入法程式介面》

整体代码如下:

文件:TSF.cs

该文件定义了 TSF 的结构以及各个方法的接口。其来源来自 C++ 的头文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

///
//               Microsoft Text Service Framework Declaration
//                        from C++ header file
//
//
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
namespace TSF
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct TF_LANGUAGEPROFILE
    {
        internal Guid clsid;
        internal short langid;
        internal Guid catid;
        [MarshalAs(UnmanagedType.Bool)]
        internal bool fActive;
        internal Guid guidProfile;
    }
    [ComImport, SecurityCritical, SuppressUnmanagedCodeSecurity,
Guid("1F02B6C5-7842-4EE6-8A0B-9A24183A95CA"),
     InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface ITfInputProcessorProfiles
    {
        [SecurityCritical]
        void Register(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        void Unregister(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        void AddLanguageProfile(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        void RemoveLanguageProfile(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        void EnumInputProcessorInfo(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        int GetDefaultLanguageProfile(short langid, ref Guid catid, out Guid clsid, out Guid profile);
        [SecurityCritical]
        void SetDefaultLanguageProfile(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        int ActivateLanguageProfile(ref Guid clsid, short langid, ref Guid guidProfile);
        [PreserveSig, SecurityCritical]
        int GetActiveLanguageProfile(ref Guid clsid, out short langid, out Guid profile);
        [SecurityCritical]
        int GetLanguageProfileDescription(ref Guid clsid, short langid, ref Guid profile, out IntPtr desc);
        [SecurityCritical]
        void GetCurrentLanguage(out short langid); //non-implement!! may be is wrong declaration.
        [PreserveSig, SecurityCritical]
        int ChangeCurrentLanguage(short langid); //non-implement!! may be is wrong declaration.
        [PreserveSig, SecurityCritical]
        int GetLanguageList(out IntPtr langids, out int count);
        [SecurityCritical]
        int EnumLanguageProfiles(short langid, out IEnumTfLanguageProfiles enumIPP);
        [SecurityCritical]
        int EnableLanguageProfile();
        [SecurityCritical]
        int IsEnabledLanguageProfile(ref Guid clsid, short langid, ref Guid profile, out bool enabled);
        [SecurityCritical]
        void EnableLanguageProfileByDefault(); //non-implement!! may be is wrong declaration.
        [SecurityCritical]
        void SubstituteKeyboardLayout(); //non-implement!! may be is wrong declaration.
    }
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("3d61bf11-ac5f-42c8-a4cb-931bcc28c744")]
    internal interface IEnumTfLanguageProfiles
    {
        void Clone(out IEnumTfLanguageProfiles enumIPP);
        [PreserveSig]
        int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
TF_LANGUAGEPROFILE[] profiles, out int fetched);
        void Reset();
        void Skip(int count);
    }
    internal static class TSF_NativeAPI
    {
        public static readonly Guid GUID_TFCAT_TIP_KEYBOARD;
        static TSF_NativeAPI()
        {
            GUID_TFCAT_TIP_KEYBOARD = new Guid(0x34745c63, 0xb2f0,
0x4784, 0x8b, 0x67, 0x5e, 0x12, 200, 0x70, 0x1a, 0x31);
        }
        [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("msctf.dll")]
        public static extern int TF_CreateInputProcessorProfiles(out ITfInputProcessorProfiles profiles);
    }
}

文件:TSFWapper.cs

这个文件封装了 TSF 的你需要调用的静态方法。更多的方法,可以在接口定义(上面文件)处找到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

public class TSFWapper
    {
        public static short[] GetLangIDs()
        {
            List<short> langIDs = new List<short>();
            ITfInputProcessorProfiles profiles;
            if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)
            {
                IntPtr langPtrs;
                int fetchCount = 0;
                if (profiles.GetLanguageList(out langPtrs, out fetchCount) == 0)
                {
                    for (int i = 0; i < fetchCount; i++)
                    {
                        short id = Marshal.ReadInt16(langPtrs, sizeof(short) * i);
                        langIDs.Add(id);
                    }
                }
                Marshal.ReleaseComObject(profiles);
            }
            return langIDs.ToArray();
        }
        public static string[] GetInputMethodList(short langID)
        {
            List<string> imeList = new List<string>();
            ITfInputProcessorProfiles profiles;
            if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)
            {
                try
                {
                    IEnumTfLanguageProfiles enumerator = null;
                    if (profiles.EnumLanguageProfiles(langID, out enumerator) == 0)
                    {
                        if (enumerator != null)
                        {
                            TF_LANGUAGEPROFILE[] langProfile = new TF_LANGUAGEPROFILE[1];
                            int fetchCount = 0;
                            while (enumerator.Next(1, langProfile, out fetchCount) == 0)
                            {
                                IntPtr ptr;
                                if (profiles.GetLanguageProfileDescription(ref langProfile[0].clsid,
                                    langProfile[0].langid, ref langProfile[0].guidProfile, out ptr) == 0)
                                {
                                    bool enabled;
                                    if (profiles.IsEnabledLanguageProfile(ref langProfile[0].clsid,
                                        langProfile[0].langid, ref langProfile[0].guidProfile, out enabled) == 0)
                                    {
                                        if (enabled)
                                            imeList.Add(Marshal.PtrToStringBSTR(ptr));
                                    }
                                }
                                Marshal.FreeBSTR(ptr);
                            }
                        }
                    }
                }
                finally
                {
                    Marshal.ReleaseComObject(profiles);
                }
            }
            return imeList.ToArray();
        }
        ///
        /// 获取当前输入法
        ///
        public static void GetCurrentLang(out string[] lang)
        {
            List<short> langIDs = new List<short>();
            ITfInputProcessorProfiles profiles;
            short id = -1;
            if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)
            {
                IntPtr langPtrs;
                int fetchCount = 0;
                profiles.GetCurrentLanguage(out id);
                Marshal.ReleaseComObject(profiles);
            }
            lang = id > -1 ? GetInputMethodList(id) : null;
        }
    }

C# TSF 输入法的获取相关推荐

  1. android 获取当前输入法,关于获取安卓手机系统输入法和设置输入法

    关于获取安卓手机系统输入法和设置输入法 获取输入法列表 adb shell ime list -s 出来下面的 io.appium.android.ime/.UnicodeIME com.sec.an ...

  2. C++ 控制当前进程输入法和控制其他进程输入法以及获取键盘大小写状态

    //当前进程输入法控制HIMC hIMC;DWORD dwConv, dwSent;hIMC = ImmGetContext(m_hwnd()当前进程窗口句柄);ImmGetConversionSta ...

  3. autoit 将输入法修改为英文输入法,获取输入法的值【20190918亲测原创】

    这是一个讨厌爬虫的人写的文章,当下的网络,把错误的文章抄的满天下都是 本人亲测win7 win2012可用,废话不多说,上代码 ;切换为英文输入法 $hWnd = WinGetHandle(" ...

  4. 基于文本服务框架的拼音输入法研究与实现

    摘要:目前的输入法大多采用输入法管理器-输入法编辑器(IMM-IME)进行开发,对于微软发布的新型输入法技术―文本服务框架(TSF)的研究一直比较滞后,该文论述了 TSF 的基本构成.主要接口.输入法 ...

  5. 逗比的输入法实现(二):基础概念和常用接口

    为什么叫 Meow?因为这是给猫用的输入法... 目录 (一):基本情况 (二):基础概念和常用接口 (三):整体构架 (四):编辑和候选 (五):界面管理和无界面模式 (六):词库和候选算法 (七) ...

  6. Android设置默认输入法

    先安装想要设置默认的输入法 获取系统已安装的输入法ID /*** 获取系统已安装的输入法ID** @param context* @return*/public static String[] get ...

  7. C# 切换中英文输入法

    本文经原作者授权以原创方式二次分享,欢迎转载.分享. 原文作者:唐宋元明清 原文地址:https://www.cnblogs.com/kybs0/p/10298697.html C# 切换中英文输入法 ...

  8. android 输入法 确定按钮,Android 输入法笔记

    首先,目前只是记录一些开发输入法时遇过的坑. 一.关于中文输入法 1.Android中文输入法资料实在是少的可怜,唯一能用的开源中文输入法就是谷歌中文输入法,但那也是很旧的版本了,只有26键并且词库也 ...

  9. 小狼毫(RIME)输入法引擎

    RIME | 中州韻輸入法引擎 RIME的中文名字有很多,比如鼠鬚管.小狼毫.中州韻(韵)等,每个人喜欢的称号各不相同,我是偏喜欢小狼毫的,以下也都简称小狼豪.小狼毫是一个跨平台的输入法算法框架,而且 ...

最新文章

  1. 有了这几个神器,瞬间逼格就上去了
  2. Xamarin Android提示找不到资源属性定义
  3. mysql丢失召回_mysql笔记
  4. mysql数据太大,如何导入_MySQL导入文件过大怎么办
  5. 米莱狄机器人怎么那么多_王者荣耀排位遇到米莱狄太恶心?三大短板可以轻松克制!...
  6. C# MemoryStream先写后读的奇怪现象
  7. python 中的三元表达式(三目运算符)
  8. 前端学习(511):两列布局的第一种方式
  9. java并发condition_Java并发之Condition的实现分析
  10. codevs 3981 动态最大子段和
  11. 更换系统后无法catkin_make universal robot 包
  12. 快速排序的C++实现
  13. 4.智能快递柜(通信篇-SOCKET)
  14. linux中硬链接为什么不能跨分区
  15. android Qwerty 键盘搜索联系人分析与实现(支持多音字)
  16. 单相变压器的平衡方程式
  17. windows安装gensim
  18. C语言写个简单的串口调试助手
  19. ZZULIOJ-1525-小P找座位
  20. 第三方登录(QQ登陆)实现

热门文章

  1. php 输出时区,PHP 输出的各个时区对应的时差表
  2. 怎么计算机械表的正负时差,机械表时差多少为正常?怎么测量误差呢?-复刻表问答-世家表行官网...
  3. 复古风的小鱼缸,还有幻彩灯效加持,忆趣TV3.0体验
  4. 人生坎坎坷坷,跌跌撞撞那是在所难免
  5. 考研英语词汇文章3-Salt
  6. 海康视频行为分析仪接入
  7. Github css加载失败,样式混乱解决办法
  8. 先转行从零基础入门学编程可以吗?
  9. 详解清除MongoDB所占用的多余的磁盘空间的方法
  10. Python每日学习-函数