原文:Win7 64位系统,使用(IME)模式VS2010 编写 和 安装 输入法 教程(1)

首先感谢:
http://blog.csdn.net/shuilan0066/article/details/6884483输入法 编程分析
http://blog.csdn.net/mspinyin/article/details/6141599输入法的注册、安装和卸载
http://www.setoutsoft.cn/Html/?256.html 浅谈输入法编程
http://wenku.baidu.com/view/3d179422bcd126fff7050b9d.html输入法漫谈
这些文章作者的无私奉献。

TSF(Text Service Framework)WIN7

写这篇文章的动机是:由于Win7 64 位系统的普及,按照上面这些文章来编写自己的输入法会遇到很多意想不到的问题。至今网络上没有找到现成详细的解决方案。我通过一周的摸索和总结,深知靠自己摸索编译成功并安装一个可以在win7 64位系统下运行的输入法是多么的艰难。 特将自己的经验拿出来和大家分享。

编写输入法有几种方式,如外挂式,IME式,TSF式,今天我们主要介绍IME式( 输入法接口式(Input Method Editor-IME))

1,输入法是什么东西? 
编写输入法其实就是编写一个DLL ,一个导出一些操作系统约定函数的DLL,操作系统通过这些函数和我们的程序交互,将用户输入的编码转换成汉字通过消息传送给应用程序(如记事本,word,)。用现在的话来说就是实现一个“接口”。

(1)操作系统如何和我们的Dll交互呢?

(2)我们编写的这个Dll就是IME


输入法工作原理 如下图:

(上图来自于:http://blog.csdn.net/shuilan0066/article/details/6883629 输入法工作原理)

2,具体我们应该做哪些工作呢?
(1)首先编写一个DLL,导出IME规定的函数。
注意这个DLL除了必须导出IME规定的函数外,还要满足如下条件。
包含一个.rc 的资源文件。包含一个Version资源
如下图划红线的部分必须设置成:FILETYPE : VFT_DRV FILESUBTYPE : VFT2_DRV_INPUTMETHOD 
否则输入法无法加载。


(2)如何导出这些函数呢?
通过def文件导出函数。然后如下图设置。 使用def文件导出dll函数的好处是,导出的函数名不会变化。


(3)要导出哪些函数,这些函数有什么用呢?
IME要求导出的有十几个函数。可真正重要的只有几个。
输入法初始化:

ImeInquire: 刚选择某输入法时,IMM调用此函数,获得输入法相关信息
BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption)
{
if (!lpIMEInfo) return (FALSE);

lpIMEInfo->dwPrivateDataSize = 0;
lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | 
#ifdef _UNICODE
IME_PROP_UNICODE |
#endif
IME_PROP_SPECIAL_UI |
IME_PROP_END_UNLOAD; //会让输入法随应用程序的退出而退出,这个在调试程序的时候特别重要,我们重新编译了程序就无需
//重启电脑,就可以更换输入法程序,进行调试。

lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE;
lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE;
lpIMEInfo->fdwUICaps = UI_CAP_2700;
lpIMEInfo->fdwSCSCaps = 0;
lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;
_tcscpy(lpszUIClass, UICLASSNAME);

return TRUE;
}

ImeSelect: 打开或关闭输入法时被调用,在此函数中对输入法上下文进行初始化或恢复释放,
在打开输入法时 fSelect为TRUE, 在关闭输入法时fSelect为FALSE

将键盘消息转换为相应汉字:
ImeProcessKey :处理键盘消息: IMM通过此函数,对键盘消息进行分类筛选,一类可以直接发给应用程序,一类需要发送给IME进行转换 ,返回值为FALSE,说明键盘消息被直接发送给了应用程序; 返回值为TRUE 说明键盘消息被发送给了IME,被发送IME后,IMM会立即调用ImeToAsciiEx对键盘消息进行转换。

ImeToAsciiEx :输入法编程最重要部分----- 此函数将进过ImeProcessKey 筛选,通过IMM传递过来的键盘消息转换为composition写作窗口中的字符串,然后再查找码表,更新候选窗口,最后选择某候选字符作为最终结果,通过消息传递给应用程序。

(4)我们的输入法怎么显示和更新写作窗户,候选窗口,怎么把用户选择的汉字传递给应用程序,通过什么机制呢?
写作窗口:就是显示和编辑用户输入字符串的窗口,比如输入的是拼音


侯选窗口:就是显示符合用户输入编码的汉字,供用户选择。通常写作窗口和获选窗户可以合二为一。

首先我们要了解两个概念:
<1>UIWnd 和UIWndProc
<2>输入法上下文(HIMC)

我们都知道windos是通过消息来运作的,要显示,更新 输入法的写作和候选窗口,就需要有消息循环。
而输入法是一个插件,他需要依靠应用程序中用户的输入消息,来控制输入法写作和候选窗口的显示和更新。
可应用程序的消息怎样才能传递给输入法呢?
IME要求我们自建的输入法dll导出一个接口,原型如LRESULT WINAPI UIWndProc(HWND hUIWnd, UINT message,WPARAM wParam, LPARAM lParam),
而User.exe(一个系统进程) 会创建一个UIWnd ,这个窗口不会显示,就是它充当应用程序和输入法之间windos消息的传递。在这个窗口的消息循环中会调用我们输入法dll导出的接口:UIWndProc。 传递过来的HWND hUIWnd 就是这个窗口的句柄,它是输入法中创建的窗口如写作窗口,候选窗口的宿主(Owner)。
上面我们说了应用程序怎么把消息传递给输入法,下面我们说说输入法怎么把它的消息和数据传递给应用程序?
User.exe(一个系统进程) 会为应用程序分配一片内存,而HIMC就是这片内存的句柄,我们称之为输入法上下文。我们将输入法要传递给应用程序的消息和数据存入这片内存,再由User.exe 传递给应用程序。

下面我们我简单介绍一下消息和数据传递的具体方法。
首先要获得HIMC,通过UIWnd的句柄g_hUIWnd 使用ImmLockIMC
HIMC hIMC = (HIMC)GetWindowLong(g_hUIWnd, IMMGWL_IMC);
*lpIMC = (LPINPUTCONTEXT)ImmLockIMC(*hIMC)
然后向HIMC中写入消息
if (IsWindow(lpIMC->hWnd))
{

LPTRANSMSG lpTransMsg;

if (!(lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf,(lpIMC->dwNumMsgBuf+1) * sizeof(TRANSMSG))))
goto Error;

if (!(lpTransMsg = (LPTRANSMSG)ImmLockIMCC(lpIMC->hMsgBuf)))
goto Error;
//将消息写入HIMC中
lpTransMsg += (lpIMC->dwNumMsgBuf);
lpTransMsg->message=message;
lpTransMsg->wParam=wParam;
lpTransMsg->lParam=lParam;
lpIMC->dwNumMsgBuf++;

ImmUnlockIMCC(lpIMC->hMsgBuf);
//将消息发送到IME,IME再决定是自己处理还是继续发给应用程序
ImmGenerateMessage(hIMC);
}

向HIMC中写入数据,将用户选择的汉字传递给应用程序。

lpIMECompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);

if (fFlag) 
{
lpResultStr = GetResultStr();//用户选择的汉字字符串
if (!lpResultStr) return FALSE;
//将用户选择的字符串写入HIMC中
_tcscpy((LPTSTR)((LPBYTE)(lpIMECompStr) + (lpIMECompStr)->dwResultStrOffset), lpResultStr);
lpIMECompStr->dwResultStrLen = _tcslen(lpResultStr);
}
ImmUnlockIMCC(lpIMC->hCompStr);

同时将用户选择的汉字传递给应用程序需要消息的协助。 
分别是WM_IME_STARTCOMPOSITION、WM_IME_COMPOSITION和WM_IME_ENDCOMPOSITION,它们分别指示开始输入编码,输入编码或者结果(视参数而异)及编码输入完成 ,WM_IME_STARTCOMPOSITION和WM_IME_ENDCOMPOSITION需要成对使用。
当发送WM_IME_COMPOSITION (GCS_COMPREAD|GCS_COMP|GCS_CURSORPOS|GCS_DELTASTART|GCS_RESULTREAD|GCS_RESULT),消息时候,IME将HIMC中lpIMECompStr 中的汉字通过WM_IME_CHAR, 消息传递给应用程序。或者转换成WM_CHAR消息传递给应用程序。

上面总结了输入法编程的基本原理。

3,输入法的安装和调试
64位系统 的输入法安装和32位系统不同。64位系统兼容32位系统的应用程序,可输入法不行,64位的应用程序必须有64位的输入法,而32位程序必须有32位的输入法。
所以我们要在64位系统中安装输入法,首先必须将我们的输入法dll编译成64位和32位两种。
(1)如何编译64位的程序呢?使用64位的操作系统,在VS2010中打开 菜单:生成-》配置管理器



(2)如何安装输入法? 
将编译的dll扩展名改成.ime
<1>拷贝输入法dll到系统目录。将64位编译的dll放入 c:\windows\system32 目录,将32位编译的放入C:\Windows\SysWOW64目录
<2>将输入法注册,网上说可以使用ImmInstallIME 函数,可我在64位系统上始终没有成功。于是使用手动创建注册表项来实现输入法的注册

A.在注册表中HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Keyboard Layouts,创建一个新的Key,名字为xxxx0804 (低位表示语言,这里0804表示简体中文;高位表示设备句柄,0000表示默认的physical layout,如00000804表示简体中文英文键盘)。譬如:

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Keyboard Layouts/E0200804]

"IME File"="***.IME" //你的输入法dll的文件名
"Layout File"="kbdus.dll"
"Layout Text"="****输入法 2010"

B. Enable这个输入法,譬如:

[HKEY_CURRENT_USER/Keyboard Layout/Preload]

"1"="00000804"
"2"="e0200804" //按照已有最大的序号+1 = 上面你创建的key的名字:E0200804

C,重新启动系统

(3)如何调试输入法
按照上面的方法按照好输入法以后,我们就可以使用VS2010对输入法进行调试。
<1> 使用附加到进程的方式



然后再窗口选择 写字板,或者word,等进程,

然后,设置断点,在记事本中选择你自己编写的输入法,输入编码,进行调试。


<2>设置命令参数为记事本程序的路径。c:\\windows\\system32\\notepad.exe

 

(4)关于编译源程序可能会遇到的问题
1、确保应用 Imm32.lib


 

2、如果 IMM.H 的位置在项目中,应在 additional include directories 中指定为./

Win7 64位系统,使用(IME)模式VS2010 编写 和 安装 输入法 教程(1)相关推荐

  1. win764位mysql免安装_win7 64位系统 下的mysql 5.6 免安装版配置

    2.修改my.ini 文件 copy default.ini 并修改 [client] port=3306 default-character-set=utf8 #客户端字符类型,与服务端一致就行,建 ...

  2. 苹果系统虚拟计算机win7,Mac虚拟机安装Win7 64位系统教程_苹果虚拟机安装Win7真的很简单...

    使用苹果笔记本的朋友一开始都是MAC原装系统,当然对于要玩游戏和工作的朋友来说Mac肯定不行,不管是工作需要还是测试在苹果电脑上安装Win7系统都是必要的,除了安装双系统之外,Mac虚拟机安装Win7 ...

  3. win7 64位系统 c#无法利用OleDbConnection打开扩展名为xlsx的excel文件

    一.运行环境 win7 64位系统 office 2007,只有32位 vs2010 C# 使用OLEDB读取excel 二.相关代码及错误现象 // 默认读取.xls文件 string strCon ...

  4. 电脑打开回收站显示服务器运行失败,win7 64位系统无法清空回收站的故障原因及解决方法...

    运行win7系统一段时间后,为提高运行速度,会删除一些不常用或无用的文件.删除的无用文件都是放在回收站里面的,主要是方便用户直接恢复.所以大家需要在win7 64位系统回收站里面在彻底清除一次文件, ...

  5. 计算机未识别网络什么意思,win7 64位系统提示当前连接到未识别的网络怎么办...

    win7系统用户如果想要更好的操作使用电脑,就必须电脑连上网络.不过有笔记本Win7系统用户反映电脑进行本地连接后,系统桌面任务栏右下角却弹出"当前连接到未识别的网络"的提示,其实 ...

  6. win7 64位系统oracle客户端访问远程数据库

    今天将win7 64位系统oracle客户端访问远程数据库配置成功,由于我用的是64位的win7操作系统,在网上查了很多资料都说在64位系统下oracle客户端配置很复杂,于是自己亲手试了一下成功了, ...

  7. Win7 64位系统,PHP 扩展 curl方法

    网上给出了很多解决方法都为解决,现分享如下: win7 64位系统,apache24,PHP5.6.6. 除了将PHP.ini中的;extension=php_curl.dll前面的";&q ...

  8. WIN7 64位系统搭建WINCE6.0系统遇到的问题

    WIN7 64位系统搭建WINCE6.0系统遇到的问题 安装顺序如下: 1.先装Visual Studio2005: 2.安装Visual Studio2005 Service Pack 1: 3.安 ...

  9. WIN7 64位系统注册银行支付组件

    WIN7 64位系统注册银行支付组件 目前只尝试注册了银联的chinapay.dll和工行的icbcebankutil.dll 1.将dll文件拷贝到windows\syswow64\文件夹下(Win ...

最新文章

  1. WinForm 应用程序中开启新的进程及控制
  2. java数据库编程(JDBC)
  3. linux权限补充:rwt rwT rws rwS 特殊权限
  4. STL-红黑树源码实现
  5. linux下执行scrapy的爬虫定时任务
  6. GCDPlot 0.31 发布
  7. python网页爬虫例子_Python网络爬虫 - 一个简单的爬虫例子
  8. markdown中快速插入Emoji表情包语法速查表!!!
  9. At present, Huawei has two more important
  10. 外文翻译 matlab与矩阵处理,外文文献及译 MATLAB 介绍.doc
  11. linux系统挂载光盘镜像ISO的方法
  12. 软件系统设计-1-软件设计原则
  13. 2022全球「高被引科学家」榜单出炉!中国内地1169人入选,继续紧追美国
  14. Ubuntu20.04 linux Erlang编程----毕达哥拉斯定理
  15. 【python教程入门学习】拒绝反爬虫 教你爬虫验证码
  16. 团队协作之 Git 提交
  17. Java面试——消息队列
  18. 简单的购物车和购物车结算
  19. 小米book pro16笔记本怎么U盘安装系统教学分享
  20. 什么软件可以拍照翻译?4款让你沟通无障碍

热门文章

  1. css32D、3D、动画、过渡
  2. CSS3 移动端开发技巧
  3. Java反射机制(Reflection)
  4. PCB设计--PCB画图技巧
  5. PAT乙级 1038 统计同成绩学生(map的解法)
  6. C/C++面试例题讲解
  7. mongodb 持久化 mysql_(转)mongodb与mysql区别
  8. 单调队列以及单调队列优化DP
  9. Android演示Stack(课下作业)
  10. ios batchRequest