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:
整体代码如下:
文件: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 输入法的获取的更多相关文章
- Android输入法框架系统(上)
输入法,就是用来输入字符(包括英文,俄文,中文)的工具.输入法你可以看成是一种字符发生器,它将输入数据触摸事件或者按键事件转化为其他更丰富的字符.在PC时代,输入法的原始输入来自实体键盘,鼠标,然后输 ...
- Rime 小狼毫 注意事项
https://rime.im/https://github.com/rime/weasel/pulse 打不出中文可能是,没有五笔需要的文件: wubi_pinyin.schema.yamlCtrl ...
- 2. Python3输入与输出
数据的输入和输出操作是计算机最基本的操作,本节只研究基本的输入与输出,基本输入是指从键盘上输入数据的操作,基本输出是指屏幕上显示输出结果的操作. 2.1基本输入和输出 常用的输入与输出设备有很多,如摄 ...
- 用Jquery控制文本框只能输入数字和字母及jquery自定义方法$.fn
封装成onlyNum(),onlyAlpha()和onlyNumAlpha()3个Jquery扩展方法,方便复用,由于里面一些JS代码涉及到了"禁用输入法,获取剪切板的内容",而& ...
- ADB常用指令
adb 命令是adb程序自带的一些命令:adb shell则是调用Android系统的命令,Android系统特有的命令都放在Android设备的/system/bin目录中 MonkeyRunner ...
- ADB 常用命令学习
参考文档:https://www.cnblogs.com/bravesnail/articles/5850335.html非常感谢作者的分享,以下是我学习的记录.Android 常用adb 命令汇总- ...
- Android输入法界面管理(打开/关闭/状态获取)
最近做一个带发表情的聊天界面,需要管理系统输入法的状态, 一.打开输入法窗口: InputMethodManager inputMethodManager = (InputMethodManager) ...
- 微软新一代输入法框架 TSF - Text Service Framework 小小的研究
实际上windows中有两套输入法框架,一套叫做imm32.一套叫做tsf,win7以后的新系统都是优先使用tsf的,现在新出的输入法基本也是基于tsf的. 你可以参考一下这篇文章,虽然是c++的代码 ...
- Android开发 - 获取系统输入法高度的正确姿势
问题与解决 在Android应用的开发中,有一些需求需要我们获取到输入法的高度,但是官方的API并没有提供类似的方法,所以我们需要自己来实现. 查阅了网上很多资料,试过以后都不理想. 比如有的方法通过 ...
随机推荐
- Nutch关于robot.txt的处理 分类: H3_NUTCH 2015-01-28 11:20 472人阅读 评论(0) 收藏
在nutch中,默认情况下尊重robot.txt的配置,同时不提供配置项以忽略robot.txt. 以下是其中一个解释.即作为apache的一个开源项目,必须遵循某些规定,同时由于开放了源代码,可以简 ...
- 【计算机】基本概念的理解 —— 沙盒(sandbox)、交互式计算/编程/应用
web scraper:网络铲: scraper:n. 刮刀:铲土机:守财奴: 1. 交互式计算/编程/应用(interactive computing/application/programming ...
- A Guide to Python's Magic Methods
Book Source:[https://rszalski.github.io/magicmethods/] magic methods: 名称前后有双下划线的方法 构造函数和初始化 初始化类实例时, ...
- jquery-11 jquery中的事件切换如何实现
jquery-11 jquery中的事件切换如何实现 一.总结 一句话总结:事件切换hover()和toggle()函数.参数两个,都是函数,依次执行两个函数. 1.如何实现单击切换图片? 用togg ...
- INotifyPropertyChanged接口的详细说明
在windows phone开发8.1:数据绑定中,我们了解了数据绑定的基本知识.今后几篇文章会继续深入了解数据绑定.今天我们来看在数据绑定中十分重要的INotifyPropertyChanged接口 ...
- 【t010】最近距离
Time Limit: 1 second Memory Limit: 32 MB [问题描述] 聚类方法要求将空间中的点集,按照一点的方式进行归类,要求每一类中的点集相互之间的距离足够的"近 ...
- Yii学习笔记之四(表单验证 api 翻译)
1.表单验证 对于用户输入的全部数据,你不能信任,必须加以验证. 全部框架如此.对于yii 能够使用函数 yii\base\Model::validate() 进行验证 他会返回boolean值的 ...
- js进阶 11-8 jquery如何获取元素相对于父元素的位置
js进阶 11-8 jquery如何获取元素相对于父元素的位置 一.总结 一句话总结:用jquery的position方法,但是使用这个方法的前提是父元素相对定位,子元素绝对定位,否则和offset ...
- java 原子量Atomic举例(AtomicReference)
java并发库提供了很多原子类来支持并发访问的数据安全性,除了常用的 AtomicInteger.AtomicBoolean.AtomicLong 外还有 AtomicReference 用以支持对象 ...
- iOS app审核参考信息地址
发件人:(苹果开发支持邮箱地址) 中国区电话:400-670-1855 chinadev<chinadev@asia.apple.com> 您好: 感谢您与 Apple 开发者计划支持 ...