标签:des style http io ar os 使用 sp for
如何初识
WINDOWS
下
IME
编程
IME
编程心得
第一章
Windows9x
系统下汉字输入法的基本原理
第二章
Windows9x
系统提供的
ime
管理函数
第三章
ime
文件中必须使用的结构
自由拼音输入法的测试
输入法程序
[ime]
的调试方法
输入法
(IME)
实现原理
大家知道,
DELPHI
许多控件有
IME
属性。这么好用的东西
VC
可没自带,怎么办呢?其
实,可通过注册表,用
API
实现。下面说一下本人对
IME
的研究结果,并提供示例工程供
大家参考
:
1
、将用到的
API
Cpp
代码
:打开注册表一键
:查询一键值
:同上
:关闭打开的键
LoadKeyboardLayout
:装载输入法
:激活输入法
2
、
IME
信息在注册表中的位置
在
HKEY_USERS:“.DEFAULT\keyboard layout\preload”
放的是已安装的输入法,下有几
个以数字为名的子键,内容是输入法代号
(keyboard layout)
,如
“e0040804”,
其中左
4
位是
设备代码
(device identifier)
,右
4
位是语言代码
(language identifier)
。例如上面:左
e004
指智能
ABC,
右
0804
指大陆中文。
(
详见
MSDN)
在
HKEY_LOCAL_MACHINE:“System\CurrentControlSet\Control\Keyboard Layouts"
放
的是已注册的输入法。他的子键名为输入法代号
(keyboard layout)
,内容为该输入法的
ime
文件,名称等信息。
3
、主要思路
我们可先把已装的输入法枚举出来
(
从注册表
)
,用户选择其一后,再激活该输入法。
两关键函数:
HKL LoadKeyboardLayout(LPCTSTR pwszKLID,UINT Flags);
第一个参数是待打开的输入法代号,如
“e0040804”(
智能
ABC);
第二个参数是标志位,如
KLF_ACTIVATE(
激活
)
。
HKL ActivateKeyboardLayout(HKL hkl,UINT Flags);
第一个参数是打开的输入法句柄
(
由
LoadKeyboardLayout
返回
);
第二个参数是标志位,如
KLF_SETFORPROCESS
。
(
详见
MSDN)
4
、例子程序
新建一基于对话框的工程,加入一
combobox
控件,增加控制变量
m_cb1
。加入一
edit
控
件,增加控制变量
m_edt1.
对
combobox,
增加对
CBN_SELCHANGE
的映射函数
OnSelchangeCombo1()
。对
edit1
,增加对
EN_SETFOCUOS
的
SetfocusEdit1().
在对话
框类头文件的
public:
下加入数组声明:
CString lst[10];
在
OnInitDialog()
的
return
前加如下代码:
Cpp
代码
HKEY
hk,hk1;
long
cp=16;
char
lp[15];
char
a[2];
a[0]=‘1‘;
a[1]=‘\0‘;
CString str,str1;
已装的输入法。注:
win2000
有所不
同
str+=a;
int
i=0;
打开键
{
a[0]++;//
下一子键
str=".DEFAULT\\keyboard layout\\preload\\";
str+=a;
if(::RegQueryValue(hk,NULL,lp,&cp)!=ERROR_SUCCESS)//
已装的输入法
MessageBox("Error");
::RegEnumKeyEx
str1="System\\CurrentControlSet\\Control\\Keyboard Layouts\\";//keyboardlay
outLayout
str1+=lp;
lst[i++]=lp;
//
打开对应的
keyboardlayoutLayout
if(RegOpenKey(HKEY_LOCAL_MACHINE,str1,&hk1)==ERROR_SUCCESS
)
{
LPBYTE
lpD=new
BYTE
[80];//DataValue
DWORD
lpT=REG_SZ;//DataType
DWORD
lpS=80; //DataSize
if(RegQueryValueEx(hk1,"Layout text",NULL,&lpT,lpD,&lpS)!=ERROR_SUC
CESS)
MessageBox("Query error",(
LPCTSTR
)lpD);
m_cb1.AddString((
LPCTSTR
)lpD);
delete lpD;
}
else MessageBox("open error");
RegCloseKey(hk1);
}
::RegCloseKey(hk);
m_cb1.SetCurSel(0);
在
OnSetfocusEdit1()
加入如下代码:
Cpp
代码
CString temp;
temp=m_cb1.GetCurSel()!=CB_ERR?st[m_cb1.GetCurSel()]:“00000409”;
HKL
hkl;
装载输入法
if(hkl==NULL) OnOK();
激活输入法
在
OnSelchangeCombo1()
加入如下代码:
Cpp
代码
即可编译运行。
5
、注意:
win2000
下有所不同。注册表
HKEY_USERS:“.DEFAULT\keyboard
layout\preload
没有子键只有以数字为名的项,值为输入法代号
(keyboard layout)
。在示例
代码中不仅提供了
WIN 9X
下的代码,也提供了
2000
下的相应代码段,具体请参考示例
工程。
IME
编程心得
一、基础知识
:(
不断补充
)
1.
输入法管理器
(IMM)
2.
输入法编程器
(IME)
3.
输入上下文
(IC)
4.
应用程序
(App)
二、
IMM-IME
结构的基本工作过程及特点
用户键盘消息
->
系统通过
IMM
传递给与当前线程对应的
IME->IME
根据输入的消息和输入
上下文中记录的数据,将用户的键盘动作转换成结果串
->
以字串消息的形式返回给
IMM->
放到应用程序窗口的消息队列中。
三、
IME
的构成
1.IME
转换接口
(IME conversion interface)
2.IME
用户接口
(IME user interface)
由用户实现的一组窗口
,
这些窗口用来接收和处理由
IMM
发来的输入消息
,
提供与用户交互
的界面
.
由下面的窗口组成
:
1)
缺省的
IME
窗口
(Default IME window)
2)
用户接口窗口
(UI interface)
3)
用户接口窗口的组件
:
状态窗口
(status window);
编码窗口
(compsition window);
候选窗口
(candidate window).
4)
软键盘和系统菜单
/
图标等
四、
IME
的实现
1.IME
转换接口的实现
这些接口函数在供管理器在适当的时候调用
.
这些函数并非每个都要进行自己的处理
,
大部
分保留一个空函数即可
,
但没有却不可
.
系统默认是要调用的
,
找不到就不行
.
有以下函数
:
1)ImeInquire
2)ImeConfigure
3)ImeProcessKey
4)ImeToAsciiEx
5)ImeSelect
6)ImeSetActiveContext
7)NotifyIME
8)ImeDestroy
9)ImeConversionList
10)ImeEscape
11)ImeSetCompsitionString
12)ImeRegisterWord
13)ImeUnregisterWord
14)ImeGetRegisterWordStyle
15)ImeEnumRegisterWord
2.IME
用户接口的实现
主要包括用户接口窗口
(
窗口类和窗口过程
),
用户界面窗口的组件
(
状态窗口
,
编码窗口和候
选窗口的窗口类和窗口过程
),
输入法的配置窗口
,
软键盘
,
任务条上的指示器窗口
(
图标
,
菜单
,
工具提示
)
和输入法热键等
.
1)
用户接口窗口
:
编程中主要是处理由缺省的
IME
窗口传入的
IME
消息
,
当然
,
并非所有的
IME
消息都需要给出具体处理
(
可以看出这是
IME
编程中的一个原则
).
如
:
WM_IME_COMPOSITION
WM_IME_STARTCOMPSITION/WM_IME_ENDCOMPOSITION
WM_IME_SELECT
WM_IME_NOTIFY
WM_IME_CHAR
五、具体实现步骤:
IME
实质上是一个
DLL
实现,由系统调用。而这个
DLL
则分别实现了系统要调用的功能
函数。所以有些函数虽然不做什么事情,但是必需挂上一个空壳。否则调用出错。
1.DLLMain()
的架构
1)
进入进程
DLL_PROCESS_ATTACH
事件中,注册用户接口窗口类及其组件的窗口类:使用
RegisterClassEx()
完成此注册过程。设置类名字段
(lpszClassName)
为用户接口窗口类类
名(包括结束标志
‘\0‘
在内最长可达
16
字符),在类风格
(style)
字段中必须包括
CS_IME
风格。设置附加内存大小(
cbWndExtra
)。
2)
退出进程
注销上述与输入法编辑器有关的窗口类,进行全局性的清理工作。
2.
打开
/
关闭输入法编辑器时进行的初始化操作
1)
用户接口窗口是由缺省的
IME
窗口在接到
WM_IME_SELECT
消息时创建的。输入法管
理器通过调用
ImeRequire
接口函数获取输入法编辑器的相关信息
(
属性、用户接口窗口
类,可选项
)
,据此进行输入法编辑器的初始化工作,创建输入法编辑器的用户接口窗口。
所以
ImeRequire
是输入法转换接口必须实现的第一个函数。
2)
在用户接口窗口被创建后,可以进行输入法编辑器全局性的一些初始化工作,比如申请
自己的私有内存,建立私有上下文等,这些工作一般在处理
WM_IME_SELECT
消息或在
接口函数
ImeSelect
中进行,也可以在窗口过程处理
WM_CREATE
消息时进行。
3.
进入进程后
:
1)
初始化词库
2)
创建字体
3)
注册窗口类
4.
在
UI
窗口建立后
,
建立写作窗口和候选窗口
各个窗口下进行各自的消息函数处理
在这里有疑问
:UI
窗口是什么
?UI
窗口处理了
IME
的好多消息
.–
解答参看
?
基于
IMM-IME
输入法接口的实现方法
下一个任务
:
看这个论文
UI
窗口是对用户不可见的
,
但是它是所有用户界面窗口的组件窗口的父窗口
,
是全部组件窗
口的管理者
.
5.
构建框架的问题
在
projects-settings-c/c++-catagory:prepossessor:additional include directories:./
避免添加系统默认的头文件
6.
注意的细节问题
:
1)global.c
中的
应详细了解其作用
,
其与
Czh.def
中的定
义有相关联的地方
.(
对我们的工程名
Czh
来说
)
2)freepy.exp : warning LNK4070: /OUT:Czh.ime directive in .EXP differs from output
filename;C:\WINDOWS\system32\freepy.ime; ignoring directive
对于这个
BUILD
中的错误
,
关联之处在于
Czh.def
中定义了
lib
的输出名为
Czh,
要求这个
lib
的输出名与
Output file name freepy
相同
.
3)
如果
.ime
名和上述
2)
中说的问题没有的话
,
且
freepy.h(
原工程
)
中的
FREEPYFILENAME
_T(“freepy.ime”)
定义正确
,
则在
HZfreepy.h
中改变以下几个文件名
与
C:\windows\system32(window xp
系统下
)
下的相关文件名相同则可
:
freepy.tab–
字库
freepysys.dic–
系统词库
freepyusr.dic–
用户词库
4)
在
ImeSelect
的函数中
,
有个注册表键值的处理与工程有关联
5)
有四条消息的遗漏
:
imm:NotifyIME
imm:NotifyIME:NI_CONTEXTUPDATED
imm:NotifyIME:NI_CONTEXTUPDATED:IMC_SETCOMPOSITIONWINDOW
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETOPENSTATUS
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETCONVERSIONMODE
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETSENTENCEMODE
在开发过程中
,
初始化的四条消息缺漏
.
考察
:
与代码有关还是与安装有关
?
自己开发安装是手动完成的
,
即通过直接改注册表来实现的
.
为了检测
,
我将自己的开发代码
工程作如下变动
:
—-settings-output file name\freepy.ime
字库词库名不变
,
但存在
system32
目录下
只要这样
,
就可以出现了上述的消息
.
这时还与
ImeSelect
下的注册表项读取无关、与
czh.h
中的文件名定义无关、与
czh.def
中的
lib
定义无关。但是在调试时,选择输入法时却可将
本工程的图标之类的调出来。这样看来,只是无法输入文字(还没实现相关的功能),目
前的结论是:四个消息的遗漏与安装有关。
7)
制作安装程序
:
仿照
freepy
的安装程序
,
制作一个自己的安装程序
,
然后重新安装
,
安装之后
要进行更新
,
也就是到输入法的添加删除界面进行删除然后再添加进来
,
注销系统之后
,
就可
以用了
.
这样安装的结果是
:
多出了上面的第二条消息
,
其它仍然不行
.–
哪究竟与谁有关系
?
是不是与
代码有关
?
只要将
,settings
中的作改变就可以实现消息补充
.
这与什么有关系
?
8)
再重新安装一次
,
这次重装是这样的
:
–HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Keyboard Layouts\
下对应
的振华输入法子项都删除
–HKEY_CURRENT_USER\Keyboard Layout\preload
下对应的本输入法的子项删除
–HKEY_LOCAL_MACHINE\software\
下的
czhhua
删除
.
这样重装之后
,
消息出现
.
7.
流程分析
:
1)
字库的装载
这个工作是在程序进入
DLL
的开始部分就执行的
,
将字典内容保存到存储区
,
以备将
COMPSTR
转成汉字时调用存储区
.
第一章
Windows9x
系统下汉字输入法的基本原理
Windows
系统下汉字输入法实际上是将输入的标准
ascii
字符串按照一定的编码规则转换
为汉字或汉字串,进
入到目的地。
由于应用程序各不相同,用户不可能自己去设计转换程序,因此,汉字输入自然而然
落到
WINDOWS
系统管理中。
一、输入法与系统的关系
键盘事件
应用程序
|
|
Windows
的
USER.EXE
|
输入法管理器
|
输入法
系统的键盘事件有
windows
的
user.exe
软件接收后,
user.exe
在将键盘事件传导输入法
管理器
(Input Method
Manager,
简称
IMM)
中,管理器
再将键盘事件传到输入法中,输入法根据用户编码字
典,翻译键盘事件为对
应的汉字
(
或汉字串
)
,
然后再反传到
user.exe
中,
user.exe
再将翻译后的键盘事件传
给当前正运行的应用
程序,从而完成汉字的输入。
二、汉字输入法的组成
微软
Windows9x
系统中汉字输入法的名称是
“Input Method Editor” ,
简称
IME,
输入法的程
序名称为
:*.ime,
数据文
件名称为
*.MB,
即通常说的输入法编码表
(
字典
).
实际上
IME
文件是一个动态连接库程序(
DLL
),它与
dll
文件没有区别,只是名称不同
而已。
一般汉字输入法都由三个窗口组成
:
状态窗口(
Status Windows)-
显示当前的输入法状态(中文还是英文等站环信息);
编码输入窗口
(Composition Windows)-
显示当前击键情况;
汉字选择窗口
(Candidates Windows)-
列出当前编码的全部汉字
(
串
),
供用户选择或查询。
上述三个窗口由基本的用户接口(
User Interface
)函数管理着。
现在我们用
Dumpbin.exe
打开微软提供的拼音输入法
(
WINDOWS\SYSTEM\WINPY.IME
)看看它有什么组成(这里一
WINDOWS98
为例,并假定
windows
系统安装在
c:
盘下):
Cpp
代码
c:\windows\system\winpy.ime
Microsoft ? COFF Binary File Dumper Version 6.00.8168
Copyright ? Microsoft Corp 1992-1998. All rights reserved.
Dump of file WINPY.IME
File Type: DLL
//
IME
实际为
dll
程序
Section contains the following exports for WINPY.ime
0 characteristics
34A37323 time date stamp Fri Dec 26 17:04:35 1997
0.00 version
1 ordinal base
19 number of functions //
共有19个函数
//
对应19个名称
ordinal hint RVA name
1 0 0000A010 CandWndProc
//”
选择汉字窗口
"
注册函数
//”
输入编码窗口
"
注册函数
//
配置当前
ime
参数函数
将字符或字符串转换成目标字符
//
退出当前使用的
IME
6 5 000030D0 ImeEnumRegisterWord
7 6 0000FFB0 ImeEscape //
应用软件访问输入法的接口函数
.
8 7 00003080 ImeGetRegisterWordStyle
9 8 0000E9A0 ImeInquire
//
启动并初始化当前
IME
输入法
//IME
输入键盘事件管理函数
向输入法字典注册字符串
启动当前
IME
输入法
设置当前的输入处于活动状态
.
由应用程序设置输入法编码
//
将输入的键盘事件转换为汉字编码事件
删除被注册的字符串
.
//IME
事件管理函数
//
状态窗口注册函数
//
用户界面接口函数
Summary
5000 .ShareDa
7000 .data
2000 .idata
1000 .rdata
3000 .reloc
5000 .rsrc
2000 .sgroup
18000 .text
从上述可以看出,
IME
程序共有19个出口函数组成,每一个函数都有特定的格式,它们
担负着与
windows
系统传递信息的作用,这些函数是供
Windows
系统调用的。
三、输入法的函数简介
下面我们将介绍上述各个函数的功能及接口格式。
Cpp
代码
BOOL
ImeInquire( //
初始化
IME
lpIMEInfo,
//
用于初始化该输入法的结构地址
LPTSTR
lpszWndClass, //
当前输入法的名称
LPCTSTR
或者
dword lpszData //
系统信息
,9X
系列值为
0,NT/2000
下有实际值
)
如果该函数初始化成功
,
返回
TURE,
否则为
FALSE
用户应该搞清楚
IMEINFO
结构
,
特关系着你设计的输入法是否成功
.
有关该结构请
看
"
结构
"
一章
.
DWORD
IMEConversionList( //
将某字符或字符串转换成目标字符串
hIMC,
//
与当前输入法相关的应用程序句柄
要转换的字符串
(
也可能是结果串
,
可由
uFlag
指定
)
转换后的字符串
(
也可能是源串
,
可由
uFlag
指定
)
DWORD
dwBufLen, //
转换后有几个字符
UINT
uFlag //
指定结果的存放位置
)
如果成功
,
返回转换后的字符串长度
BOOL
ImeConfigure( //
用户设置输入法接口
HKL
hKL, //
当前输入法句柄
HWND
hWnd, //
配置窗口的父窗口
DWORD
dwMode, //
配置什么
LPVOID
lpData //
用户设置的数据
)
该函数的功能是提供给输入法使用者一个可以更改某些隐含设置的能力
.
如果你用过别人的输入法
,
其中的
"
配置输入法
…”
功能既是也
!
对于一个初写输入法的人
,
可以不予理它
.
BOOL
ImeDestroy( //
关闭当前输入法
UINT
uReserved //
无用
(0)
)
成功返回
TURE,
否则为
FALSE
LRESULT
ImeEscape( //
用户软件访问输入法内部信息的接口
当前的应用程序句柄
UINT
uEscape, //
设置函数功能
//=IME_ESC_QUERY _SUPPORT
//=IME_ESC_RESERVED_LAST IME_ESC_RESERVED_FIRST
//=IME_ESC_PRIVATE_FIRST IME_ESC_PRIVATE_LAST
//=IME_ESC_SEQUENCE_TO_ INTERNAL
//=IME_ESC_GET_EUDC_ DICTIONARY
//=IME_ESC_SET_EUDC_ DICTIONARY
//=IME_ESC_MAX_KEY
//=IME_ESC_IME_NAME
//=IME_ESC_SYNC_HOTKEY
//=IME_ESC_HANJA_MODE
//=IME_ESC_GETHELPFILENAME(
只适应
Windows 98
和
Windows 2000)
下不可用
)
LPVOID
lpData //
当前功能所需的数据
)
如果失败
,
返回
0,
否则有个功能决定
有时
,
人们可以用此函数怀区输入法的名称、帮助文件名称等。当然,我们可以不
提供这些功能。
6
、
BOOL
ImeSetActiveContext( //
激活或搁置当前的输入法
当前用户程序句柄
BOOL
fFlag //
激活或搁置:
=TRUE
激活
=FALSE
搁置
)
成功返回
TRUE,
否则为
FALSE
、
BOOL
ImeProcessKey( //
处理应用程序传入的所有击键事件,监测是否是当前
输入法所需的
应用程序句柄
UINT
uVirKey, //
需处理的虚键
DWORD
lParam, //
击键消息参数
LPBYTE
lpbKeyState //
当前键盘状态(
256
字节)
)
如果此键是该输入法需要的,则返回
TRUE,
否则为
FALSE
只有返回
true
的击键,
IME
才去处理
、
BOOL
NotifyIME( //
输入法选择窗口状态管理函数:
当前的应用程序句柄
DWORD
dwAction, //
状态值
DWORD
dwIndex, //
与状态值有关的序号
DWORD
dwValue //
与状态值有关的值
)
状态值说明:
打开编码选择窗口
关闭当前的编码选择窗
选摘编码
此时:
dwIndex
被选择的编码列表序号
.
被选中的编码在当前的编码列表中的序号
改变当前的编码列表(按
pageup
等键操作)
此时:
dwIndex
被选择的编码列表序号
.
不用
设置编码开始页号
此时:
dwIndex
被改变的编码列表序号
新页的开始序号
.
改变编码列表页的大小
此时:
dwIndex
当前编码页序号
新的页大小
更新应用程序的信息的输入法的信息:移动位置,设置
模式,设置编码窗口,字体。
此时:
dwIndex
只用
于
dwValue=IMC_SETCONVERSIONMODE, IMC_SETSENTENCEMODE
可取由
WM_IME_CONTROL
发送的下列值
:
IMC_SETCANDIDATEPOS
IMC_SETCOMPOSITIONFONT
IMC_SETCOMPOSITIONWINDOW
IMC_SETCONVERSIONMODE
IMC_SETSENTENCEMODE
IMC_SETOPENSTATUS
=NI_COMPOSITIONSTR
改变编码窗口中的编码
此时:
dwIndex
取下列值:
CPS_COMPLETE
完成编码转换
转换编码
取消当前的编码
清除编码,并关闭编码窗
不用
此函数成功,返回
TRUE
,否则为
FALSE
、
BOOL
ImeSelect( //
初始化输入法
当前应用程序句柄
BOOL
fSelect //
是否初始化当前输入法,
TRUE
表示初始化
)
返回:成功返回
true
,否则为
FALSE
The ImeSetCompositionString function is used by an application to set the IME
composition string structure with the data contained in the lpComp or lpRead
parameters. The IME then generates a message.
10
、
BOOL
WINAPI ImeSetCompositionString( //
将编码窗口中输入的编码保存
的编码结构中,
同志发送编码完成的消息
(
WM_IME_COMPOSITION
)给系统,
当前的应用程序句柄
DWORD
dwIndex, //
设置此函数功能
//=SCS_SETSTR
//=SCS_CHANGEATTR
//=SCS_CHANGECLAUSE
//= SCS_QUERYRECONVERTSTRING
//=SCS_RECONVERTSTRING
//=SCS_SETRECONVERTSTRING
LPCVOID
lpComp, //
编码数据区
DWORD
dwCompLen, //
编码数据区长度
LPCVOID
lpRead, //
读入的编码数据
DWORD
dwReadLen //
读入的编码数据长度
)
、
UINT
ImeToAsciiEx( //
转换编码称汉字(串)
UINT
uVirKey, //
虚键
UINT
uScanCode, //
扫描码
LPBYTE
lpbKeyState, //
用户定义的键盘状态
LPDWORD
lpdwTransBuf, //
转换后的数据存放区
UINT
fuState, //
活动菜单标志
当前的应用程序句柄
)
返回:返回值表示有几个消息,可理解为:本编码对应的汉字串有几个汉字组成
(当然,这并不相等)。
、
BOOL
WINAPI ImeRegisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString
)
13
、
BOOL
WINAPI ImeUnregisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString
)
14
、
UINT
WINAPI
ImeGetRegisterWordStyle(
UINT
nItem,
LPSTYLEBUF lpStyleBuf
)
15
、
UINT
WINAPI ImeEnumRegisterWord(
hKL,
REGISTERWORDENUMPROC lpfnEnumProc,
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString,
LPVOID
lpData
)
16
、
DWORD
WINAPI ImeGetImeMenuItems(
HIMC hIMC,
DWORD
dwFlags,
DWORD
dwType,
LPIMEMENUITEMINFO lpImeParentMenu,
LPIMEMENUITEMINFO lpImeMenu,
DWORD
dwSize
四
.ime
的版本信息
(
与普通
DLL
的区别
)
Cpp
代码
VERSIONINFO
代表字符
含义
4,0,0,950 //4.00.950 95
版
PRODUCTVERSION 4,0,0,950 //4.00.950 95
版
FILEFLAGSMASK 0x3fL
0xaL
FILEOS 0x10004L //VOS_DOS_WINDOWS32 WIN32
软件
,
可在
DOS
下运行
FILETYPE 0x3L //VFT_DRV
驱动程序
FILESUBTYPE 0xbL //VFT2_DRV_INPUTMETHOD
输入法驱动程序
BEGIN
BLOCK “StringFileInfo”
BEGIN
BLOCK “080403a8”
BEGIN
VALUE “Comments”, “\0”
VALUE “CompanyName”, "
唐码软件开发工作室
\0”
唐码输入法
版本
1.0\0”
VALUE “FileVersion”, “4.00.950\0”
VALUE “InternalName”, "
唐码输入法
版本
1.0\0”
唐码软件开发工作室
1999-1999\0”
VALUE “LegalTrademarks”, “\0”
VALUE “OriginalFilename”, “TM.IME\0”
VALUE “PrivateBuild”, “\0”
VALUE “ProductName”, "
唐码输入法
版本
1.0\0”
VALUE “ProductVersion”, “4.00.950\0”
VALUE “SpecialBuild”, “\0”
END
第二章
Windows9x
系统提供的
ime
管理函数
上一章
,
我们介绍了
ime
文件中必须设计的函数
,
这些函数要靠我们自己来设计。要完成这
些函数的设计,
需用到
windows
系统提供的管理函数
(Input Method Manager,
简称
IMM)
。
IMM
函数可以被
IME
函数使用,也可用于应用软件直接管理
IME
。
相关术语:
(1)input method context
简称
IMC–
输入法相关部分,在这里解释为:相关连的应用程序
(进程)
(2)component of the input context
简称
IMCC–IMC
的部件,是
INPUTCONTEXT
结构的
成员。
一、
IME
中使用的
IMM
函数清单
Cpp
代码
//
取编码窗口信息
//
设置编码窗口信息
//
取选择窗口信息
//
设置选择窗口信息
//
取编码窗口的某一信息
//
设置编码窗口的某一信息
//
取编码字体
//
设置编码字体
//
取选择区中编码数
取选择区中编码
ImmGetGuideLine
ImmGetConversionStatus //
取当前输入法的状态(
ACSII,SHAPE,FULL
等)
重新获得选择区转换表
取输入法打开属性
设置输入法状态
设置输入法打开状态
通报
IME
,输入法状态被改变
将我们的汉字串法发送到与当前输入法相关联的应用软件
中
向应用程序发送
WM_IME_REQUEST
获取当前
IMC
的
INPUTCONTEXT
结构信息,增加
IMC
计数器
释放
IMC
计数器
取计数器值
创建
INPUTCONTEXT
结构的一个成员
删除
IMC
成员缓冲区
取
IMCC
缓冲地址,同时使
IMCC
的计数器值增加
递减
IMCC
计数器
重新设置
IMC
的成员的缓冲区大小
取
IMC
成员的缓冲区大小
返回
IMC
计数器值
取输入法状态键,该函数供控制面板使用
设置输入法的热键
产生一个软键盘
销毁软键盘
显示或隐藏软键盘
二、
IMM
函数使用格式说明
Cpp
代码
、
BOOL
WINAPI ImmGenerateMessage( //
将我们的汉字串法发送到与当前输入
法相关联的应用软件中
HIMC hIMC //
与当前输入法相关联的应用软件的句柄,
该结构的
hMsgBuf
项即为汉字串消息
)
成功为
TRUE
,否则为
FALSE
、
LRESULT
WINAPI ImmRequestMessage( //
向应用程序发送
WM_IME_REQUEST
只是用于
w98
及
w2000
hIMC,
//
与当前输入法相关联的应用软件的句柄
WPARAM
wParam, //
与
WM_IME_REQUEST
相关的
wP
LPARAM
lParam //
与
WM_IME_REQUEST
相关的
LP
//=IMR_COMPOSITIONWINOW
//=IMR_CANDIDATEWINDOW
//=IMR_COMPOSITIONFONT
//=IMR_RECONVERTSTRING
//=IMR_CONFIRMRECONVERTSTRING
//=IMR_QUERYCHARPOSITION
//=IMR_DOCUMENTFEED
)
3
、
LPINPUTCONTEXT WINAPI ImmLockIMC( //
获取当前
IMC
的
INPUTCONTEXT
结构信息,增加
IMC
计数器
当前应用程序句柄
)
成功返回
INPUTCONTEXT
结构指针,否则为
NULL
、
BOOL
WINAPI ImmUnlockIMC( //
释放
IMC
计数器
当前应用程序句柄
)
返回
:
如果
IMC
计数器被减少到
0
了
,
返回
FALSE,
否则为
TRUE.
注意
:ImmLockIMC
与
ImmUnlockIMC
必须成对出现
,
必须是相同的
HIMC
、
HIMCC WINAPI ImmGetIMCLockCount( //
取计数器值
当前应用程序句柄
)
如果成功返回
HIMC
的计数器值,否则为
NULL.
、
HIMCC WINAPI ImmCreateIMCC( //
创建
INPUTCONTEXT
结构的一个成员
DWORD
dwSize //
成员的缓冲区长度
)
如果成功返回
IMC
的成员句柄,否则为
NULL
、
HIMCC WINAPI ImmDestroyIMCC( //
删除
IMC
成员缓冲区
被删除的
IMC
的成员
)
如果成功返回
NULL
,否则等于该
HIMCC.
、
LPVOID
WINAPI ImmLockIMCC( //
取
IMCC
缓冲地址,同时使
IMCC
的计数
器值增加
成员句柄
)
If the function is successful, the return value is the pointer for the IMC component
.
Otherwise, the return value is NULL.
9
、
BOOL
WINAPI ImmUnlockIMCC( //
递减
IMCC
计数器
成员句柄
)
如果
IMCC
的计数器值为零,则返回
FALSE
,否则为
TRUE.
、
HIMCC WINAPI ImmReSizeIMCC( //
重新设置
IMC
的成员的缓冲区大小
的成员句柄
DWORD
dwSize //
新缓冲区大小
)
如果成功,返回新的
HIMCC
,否则为
NULL.
、
DWORD
WINAPI ImmGetIMCCSize( //
取
IMC
成员的缓冲区大小
成员句柄
)
返回
IMC
成员的缓冲区大小
、
DWORD
WINAPI ImmGetIMCCLockCount( //
返回
IMC
计数器值
成员的句柄
)
成功返回该
IMCC
的计数器值,否则为
0
、
BOOL
WINAPI ImmGetHotKey( //
取输入法状态键,该函数供控制面板使用
DWORD
dwHotKeyID,
LPUINT lpuModifiers,
LPUINT lpuVKey,
LPHKL lphKL
)
14
、
BOOL
WINAPI ImmSetHotKey( //
设置输入法的热键
DWORD
dwHotKeyID,
UINT
uModifiers,
UINT
uVKey,
hKL hKL
)
15
、
HWND
WINAPI ImmCreateSoftKeyboard( //
产生一个软键盘
UINT
uType, //
软件盘上的键码含义的定义方式
//=SOFTKEYBOARD_TYPE_T1
//=SOFTKEYBOARD_TYPE_C1
UINT
hOwner, //
该输入法的
UI
窗口
int
x, //
定位坐标
int
y //
定位坐标
)
成功返回软键盘的窗口句柄
、
BOOL
WINAPI ImmDestroySoftKeyboard( //
销毁软键盘
HWND
hSoftKbdWnd //
软年盘窗口句柄
)
成功为
TRUE,
法哦则为
FALSE.
、
BOOL
WINAPI ImmShowSoftKeyboard( //
显示或隐藏软键盘
HWND
hSoftKbdWnd, //
软年盘窗口句柄
int
nCmdShow //
窗口状态
=SW_HIDE
表示隐藏,
=SW_SHOWNOACTIVATE
表
示显示
)
如构成功返回
TRUE.
否则为
FALSE.
第三章
ime
文件中必须使用的结构
前二章我们讲述了
ime
和
imm
函数
,
二者之间是靠下列结构通讯的。
Cpp
代码
、
IMEINFO
struct tagIMEInfo { //
输入法的接口信息
用于
ImeInquire
函数中
DWORD
dwPrivateDataSize;//
用户设计的数据结构的字节数
DWORD
fdwProperty; //
输入法对键盘事件的相应特性
其中其高字可为下列字节位的组合:
转换窗口是否放置在需插入字符的位置
该输入法具有特殊用户接口
输入法的选择窗口中汉字串的起始
序号为
1
支持
UNICODE
字符
其中其低字可为下列字节位的组合:
//=IME_PROP_END_UNLOAD
//=IME_PROP_KBD_CHAR_FIRST
首先由键盘转换字符
将
ALT
键盘事件传送到
IME
输入法内
禁止上位键事件进入输入法内
当关闭输入法时,完成编码的转
换
用于
W98
及
2000
中
DWORD
fdwConversionCaps;//
当前输入法具有的功能特性
,
如有软键、标点、中
西文切换等功能
设置活动模式
设置全角模式
设置为字符模式
设置软键盘模式
不支持模式变换
//=IME_CMODE_EUDC //
//=IME_CMODE_SYMBOL //
设置标点字符模式
DWORD
fdwSentenceCaps; //
//=IME_SMODE_PLAURALCLAUSE
//=IME_SMODE_SINGLECONVERT
//=IME_SMODE_AUTOMETIC
//=IME_SMODE_CONVERSATION
DWORD
fdwUICaps; //
用户界面能力:支持软键盘等
//=UI_CAP_2700
//=UI_CAP_ROT90
//=UI_CAP_ROTANY
//=UI_CAP_SOFKBD
DWORD
fdwSCSCaps; //
用户设置编码串的能力
//=SCS_CAP_COMPSTR
//=SCS_CAP_MAKEREAD
DWORD
fdwSelectCaps; //
输入法切换时是否使用以前输入法的模式
//=SELECT_CAP_CONVMODE
//=SELECT_CAP_SENTENCE
} IIMEINFO;
2
、
COMPOSITIONSTR
用于编码管理
用于存放编码信息的信息
:
所有的实际信
息放在本结构的后面
DWORD
dwSize; //
当前编码信息需要的存储空间
=
读入的编码
+
属性
+
子串
+
属性
+
编码
+
属性
+
结果
+
属性
DWORD
dwCompReadAttrLen; //
读入的编码属性长度
DWORD
dwCompReadAttrOffset; //
存放在内存的位置
DWORD
dwCompReadClsLen; //
读入的子串长度
DWORD
dwCompReadClsOffset; //
存放在内存的位置
DWORD
dwCompReadStrLen; //
读入的编码长度
DWORD
dwCompReadStrOffset; //
存放在内存的位置
DWORD
dwCompAttrLen; //
编码属性长度
DWORD
dwCompAttrOffset; //
存放在内存的位置
DWORD
dwCompClsLen; //
编码子串长度
DWORD
dwCompClsOffset; //
存放在内存的位置
DWORD
dwCompStrLen; //
编码串长度
DWORD
dwCompStrOffset; //
存放在内存的位置
DWORD
dwCursorPos; //
当前光标位置
DWORD
dwDeltaStart; //
被修改编码的位置
DWORD
dwResultReadClsLen; //
读入结果子串长度
DWORD
dwResultReadClsOffset; //
存放在内存的位置
DWORD
dwResultReadStrLen; //
读入的编码长度
DWORD
dwResultReadStrOffset; //
存放在内存的位置
DWORD
dwResultClsLen; //
结果子串长度
DWORD
dwResultClsOffset; //
存放在内存的位置
DWORD
dwResultStrLen; //
结果串长度
DWORD
dwResultStrOffset; //
存放在内存的位置
DWORD
dwPrivateSize; //
用户自定义数据长度
DWORD
dwPrivateOffset; //
存放在内存的位置
} COMPOSITIONSTR;
3
、
CANDIDATEINFO
用于编码选择管理
编码选择信息的信息,其后为实际编码列
表数据
DWORD
dwSize; //
数据所占内存大小
DWORD
dwCount; //
表马列表个数
DWORD
dwOffset[32]; //
各个编码列表的内存位置
DWORD
dwPrivateSize; //
自定义数据尺寸
DWORD
dwPrivateOffset; //
缓冲区位置
} CANDIDATEINFO;
4
、
GUIDELINE
typedef struct tagGUIDELINE {
DWORD
dwSize;
DWORD
dwLevel; // the error level.
// GL_LEVEL_NOGUIDELINE,
// GL_LEVEL_FATAL,
// GL_LEVEL_ERROR,
// GL_LEVEL_WARNNING,
// GL_LEVEL_INFORMATION
DWORD
dwIndex; // GL_ID_NODICTIONARY and so on.
DWORD
dwStrLen; // Error Strings, if this is 0, there
// is no error string.
DWORD
dwStrOffset;
DWORD
dwPrivateSize;
DWORD
dwPrivateOffset;
} GUIDELINE;
5
、
CANDIDATELIST
The CANDIDATELIST structure contains information about a candidate list.
typedef struct tagCANDIDATELIST { //
编码选择列表信息
=
〉管理编码窗口中的列
表信息
DWORD
dwSize; //
用字节表示的内存大小:
=sizeof(CANDIDATELIST)+
选择字符
数据
DWORD
dwStyle; //
列表串的取值方式
列表数据的格式无定义
读到什么数据即为什么数据
,
一般我们使用该属性
如果
dwCount=1
,
dwOffset
不是地址,而是实际数据,
表示地址
//=IME_CAND_MEANING
//=IME_CAND_RADICAL
//=IME_CAND_STROKES
DWORD
dwCount; //
当前列表个数
DWORD
dwSelection; //
当前选择的列表序号
DWORD
dwPageStart; //
在列表窗口中所显示的列表的起始序号(上下翻页时
用)
DWORD
dwPageSize; //
一页显示的列表个数
DWORD
dwOffset[]; //
列表数据存放区地址:
[
阿
];[
大
]
。。。。
} CANDIDATELIST;
6
、
COMPOSITIONFORM
窗口位置、大小信息:
} RECONVERTSTRING;
11
、
IMEMENUITEMINFO
输入法菜单结构,
W98/2000
UINT
cbSize;
UINT
fType;
UINT
fState;
UINT
wID;
HBITMAP
hbmpChecked;
HBITMAP
hbmpUnchecked;
DWORD
dwItemData;
TCHAR
szString[48];
HBITMAP
hbmpItem;
}
12
、
INPUTCONTEXT
The INPUTCONTEXT structure is an internal data structure that stores Input
Context data.
typedef struct tagINPUTCONTEXT { //IMC
数据存放区
HWND
hWnd; //
使用该
IMC
的窗口
BOOL
fOpen; //IME
的打开与关闭状态
状态窗口的位置
软键盘的位置
DWORD
fdwConversion; //IME
状态
(
活动、不活动,全角等)
DWORD
fdwSentence; //
编码方式
union {
LOGFONTA A;
LOGFONTW W;
} lfFont; //
字体
编码格式结构
列表选择结构
HIMCC hCompStr; //
HIMCC hCandInfo;
HIMCC hGuideLine
HIMCC hPrivate;
DWORD
dwNumMsgBuf; //
存放在
hMsgBuf
中的消息数
存放的消息,格式:
[
消息
1] [wParam1] [lParam1] {[
消
息
] [wParam2] [lParam2]…
注意
:
我们输入的汉字串存放在这里
DWORD
fdwInit //
系统根据此值来初始本结构相应的信息
初始化
ptStatusWndPos
初始化
fdwConversion
初始化
fdwSentence
初始化
lfFont
初始化
cfCompForm
初始化
ptSoftKbdPos
DWORD
dwReserve[3]; //
将来版本扩展的信息
在
UI
窗口下需要处理下列
windows
消息
.
1
、
WM_IME_SETCONTEXT
激活或休眠输入法
LRESULT CALLBACK UIWndProc(HWND hUIWnd,UINT uMsg,WPARAM
wParam,LPARAM lParam)
{
:
case WM_IME_SETCONTEXT:
fSet= (BOOL) wParam;
lISCBits = lParam;
}
如果
fSet
为
TRUE,
系统将激活当前输入法的某个窗口
(
状态窗、列表窗等),为
FALSE
时
休眠当前输入法
.
其中
lISCBits
中指出对哪个窗口操作。
数值
含义
ISC_SHOWUICOMPOSITIONWINDOW
显示编码窗口
ISC_SHOWUIGUIDWINDOW
显示信息窗口
ISC_SHOWUICANDIDATEWINDOW
显示
0
号列表窗口
(ISC_SHOWUICANDIDATEWINDOW ? 1)
显示
1
号列表窗口
.
(ISC_SHOWUICANDIDATEWINDOW ? 2)
显示
2
号列表窗口
.
(ISC_SHOWUICANDIDATEWINDOW ? 3)
显示
3
号列表窗口
.
2
、
WM_IME_CONTROL
管理当前输入法
wSubMessage= wParam;
受
WM_IME_CONTROL
控制的消息
lpData = (LPVOID) lParam;
对应的数据
其中子消息有下列消息:
1
)
IMC_GETCANDIDATEPOS
获取列表窗口的位置
.
此时
lParam
传送的是
CANDIDATEFORM
结构地址。
如果此消息成功返回
0
,否则非零。
通常如果你设计此部分了,返回
0
。否则返回
1
。
2
)
IMC_GETCOMPOSITONFONT
获取编码窗口字体结构,
lParam
为
LOGFONT
结构地址
如果此消息成功返回
0
,否则非零。
通常如果你设计此部分了,返回
0
。否则返回
1
。
3
)
IMC_GETCOMPOSITONWINDOW
获取编码窗口位置,
lParam
为
COMPOSITIONFORM
结构地址。
如果此消息成功返回
0
,否则非零。
通常如果你设计此部分了,返回
0
。否则返回
1
。
4
)
IMC_GETSOFTKBDFONT
获取软键盘字体。
lParam
字体结构
LOGFONT
地址。
5
)
IMC_GETSOFTKBDPOS
获取软键盘位置,
lParam = 0;
返回软键盘在屏幕窗口中的坐标结构
POINTS
。
6
)
IMC_GETSOFTKBDSUBTYPE
wSubMessage= IMC_GETSOFTKBDSUBTYPE;
注意:
UI
窗口不接受此消息,它的管理函数是
NotifyIME
。
11
)
IMC_SETSOFTKBDDATA
设置软键盘数据,此时
lParam
传送的是
SOFTKBDDATA
结构地址,用户设定自己的软
键盘字符。
wSubMessage= IMC_SETSOFTKBDDATA;
lpSoftKbdData= (LPSOFTKBDDATA) lParam;
如果此消息成功返回
0
,否则非零。
注意:
UI
窗口不接受此消息,它的管理函数是
NotifyIME
。
12
)
IMC_SETSOFTKBDSUBTYPE
设置软键盘类型
wSubMessage= IMC_SETSOFTKBDSUBTYPE;
lSubType= lParam;
成功返回
subtype
,否则返回
-1.
注意:
UI
窗口不接受此消息,它的管理函数是
NotifyIME
。
13
)
IMC_SETSOFTKBDFONT
设置软键盘字体,此时
lParam
传送的是
LOGFONT
结构地址
wSubMessage= IMC_SETSOFTKBDFONT;
lpLogFont= (LPLOGFONT)lParam;
如果此消息成功返回
0
,否则非零。
注意:
UI
窗口不接受此消息,它的管理函数是
NotifyIME
。
14
)
IMC_SETSOFTKBDPOS
设置软件位置,此时
lParam
传送的是
POINTS
结构
wSubMessage= IMC_SETSOFTKBDPOS;
ptsPt= (POINTS)lParam;
如果此消息成功返回
0
,否则非零。
15
)
IMC_SETSTATUSWINDOWPOS
设置状态窗口位置,此时
lParam
传送的是
POINTS
结构
wSubMessage= IMC_SETSTATUSWINDOWPOS;
ptsPt= (POINTS)lParam;
如果此消息成功返回
0
,否则非零。
3
、
WM_IME_COMPOSITION
当用户改变了编码状态时,发送此消息
WM_IME_COMPOSITION
应用程序可以通过调用
ImmGetCompositionString
获取新的编码状态。
wChar= wParam;
最后输入到编码窗口的
2
字节的
DBCS
字符
lAttribute= lParam;
当前编码的含义。
lAttribute
可取下列值得组合:
值
含义
GCR_ERRORSTR
修正错误
GCR_INFORMATIONSTR
修正信息串
GCS_COMPATTR
修正编码串属性
.
GCS_COMPCLAUSE
修正编码信息
.
GCS_COMPREADATTR
修正读入串的属性
GCS_COMPREADCLAUSE
修正读入串的属性
.
GCS_COMPREADSTR
修正读入串。
GCS_COMPSTR
修正当前的编码
GCS_CURSORPOS
修正当前编码的光标位置
.
GCS_DELTASTART
修正当前编码的开始位置
GCS_RESULTCLAUSE
修正结果串的信息
.
GCS_RESULTREADCLAUSE
修正读入串的信息
.
GCS_RESULTREADSTR
修正读入串
.
GCS_RESULTSTR
修正编码结果串
.
CS_INSERTCHAR
在当前位置插入一个字符
CS_NOMOVECARET
替换结果串
4
、
WM_IME_COMPOSITIONFULL
用户接口窗口不能增加编码窗口的尺寸时,
ime
用户接口窗口将发送
WM_IME_COMPOSITIONFULL
消息,可不处理。
wParam = 0
lParam= 0
5
、
WM_IME_ENDCOMPOSITION
当编码结束时
ime
发送此消息
WM_IME_ENDCOMPOSITION
wParam = 0
lParam= 0
用户程序可以接受此消息,以便自己显示用户输入的编码。
6
、
WM_IME_SELECT
系统发出
WM_IME_SELECT
以便选择一个新的
ime
。
fSelect= (BOOL)wParam; TRUE
表示新的
IME
已选择,
FALSE
表示不被选择或关闭该输
入法。
hKL= lParam;
系统利用这个消息产生或关闭老的输入法用户窗口。
7
、
WM_IME_STARTCOMPOSITION
当用户开始输入编码时,系统立即发送该消息到
IME
中,
IME
打开编码窗口。
wParam = 0
lParam= 0
8
、
WM_IME_NOTIFY
IME
消息组:
wSubMessage= wParam;
lParam= lParam;
各消息说明:
1
)
IMN_CLOSESTATUSWINDOW
关闭状态窗口时,系统发送
IMN_CLOSESTATUSWINDOW
消息。
wSubMessage = IMN_CLOSESTATUSWINDOW;
lParam= 0;
当用户接口窗口接收到此消息时,将关闭状态窗口。
2
)
IMN_OPENSTATUSWINDOW
产生或打开状态窗口
wSubMessage = IMN_OPENSTATUSWINDOW;
lParam= 0;
当
ime
接收到此消息时
,
将产生状态窗口
.
有关状态串口的信息可用
ImmGetConversionStatus
获取
,
设置状态窗口的信息可用
ImmSetConversionStatus.
3
)
IMN_OPENCANDIDATE
打开或产生列表选择窗口
wSubMessage = IMN_OPENCANDIDATE;
lCandidateList= lParam;
4
)
IMN_CHANGECANDIDATE
更新当前的列表选择窗口
WM_IME_NOTIFY
wSubMessage = IMN_CHANGECANDIDATE;
lCandidateList= lParam;
5
)
IMN_CLOSECANDIDATE
关闭选择窗口
wSubMessage = IMN_CLOSECANDIDATE;
lCandidateList= lParam;
UI
窗口接收此消息后
,
将销毁列表选择窗口
IMN_SETCONVERSIONMODE
改变输入法状态模式管理
wSubMessage = IMN_SETCONVERSIONMODE;
lParam= 0;
IMN_SETOPENSTATUS
设置输入法状态
wSubMessage = IMN_SETOPENSTATUS;
lParam= 0;
IMN_SETCANDIDATEPOS
设置列表窗口位置
wSubMessage = IMN_SETCANDIDATEPOS;
lCandidateList= lParam;
Parameters
IMN_SETCOMPOSITIONFONT
设置编码窗口字体
wSubMessage = IMN_SETCOMPOSITIONFONT;
lParam= 0;
IMN_SETCOMPOSITIONWINDOW
设置编码窗口
wSubMessage = IMN_SETCOMPOSITIONWINDOW;
lParam= 0;
IMN_GUIDELINE
错误信息处理
wSubMessage = IMN_GUIDELINE;
lParam= 0;
IMN_SOFTKBDDESTROYED
关闭软键盘
wSubMessage = IMN_SOFTKBDDESTROYED;
lParam= 0;
自由拼音输入法的测试
李振春先生写的自由拼音可以从下面的网址下载:
项目主页
http://gforge.osdn.net.cn/projects/freepyce
可以用:
svn checkout http://gforge.osdn.net.cn/svn/freepyce
获得最新的源码。
编程源代码后,生成
DLL
文件:
freepy.dll
。复制它和
library
目录的
freepy.tab
和
freepysys.dic
文件到
CE
设备的
windows
目录。
最好的做法,是通过
PB
将上述的三个文件集成到
CE
映像文件中,同时修改注册表。这
样将不再加载微软输入法,而加载自由拼音输入法。
用
ActiveSync
连接
CE
设备,用
Remote Register Editor
连接系统嵌入式板的注册表:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010804
修改,
把
Ime File
键值从
msimepy.dll
改为
freepy.dll
。
在
CE
设备上打开
Microsoft WordPad
程序,然后选择输入法。对自由拼音进行测试
!
注:不能使用
CE
设备上已经运行的程序,如
explorer
,或给桌面文件改名来测试。由于
系统本来的微软输入法仍然存在,它们还在调用的微软输入法。
输入法程序
[ime]
的调试方法
以自由拼音
(freepy3.1)
为例
第一步:
安装
freepy3.1
第二步:
a)
如果是
VC6.0
打开
freepy3.1
工程,打开
vc
主菜单的
Project/settings
的
Link
属性页
下的
output file name
下
输入
c:\winnt\system32\freepy.ime,
这是
win2000,
如果是
xp
则可能是
c:\windows\system32\freepy.ime
;还要在
Debug
属性页下的
Executable for
debug seesion
下输入
c:\windows\system32\notepad.exe
。
b)
如果是
VS.NET
打开
freepy3.1
工程,项目
->freepy3.1
属性,进入链接器页,设置输入
文件为
c:\windows\system32\freepy.ime
,然后进入调试页,将命令设置为:
c:\windows\system32\notepad.exe
。根据操作系统不同可能有别,请做相应修改!
第三步:
设置断点,然后按
F5
,进行调试,这时候打开任务栏右下脚输入法里的自由拼音输入法就
可以了。
完成以上几步,就可以在记事本里输入汉字,然后跟踪输入法代码,从中理解各个函数之
间的相互调用顺序!
输入法
(IME)
实现原理
一、实现原理
1.
中文输入法的组成
微软
Windows
系统中输入法由程序(
DLL
)名称为:
*.ime
文件和码表文件(字典)
名称为
*.mb
文件组成。
2.
中文输入法的界面
http://wjy.hanwenhua.com/images/Projec6.gif
3.
在
Windows
任务栏
“EN
图标
”
中增加输入法名称
这也就是
Setup
程序的关键,实际上,可以利用
Win32Api
函数
ImmInstallIME()
。
该函数的原形是:
HKL ImmInstallIME( LPCTSTR lpszIMEFileName, LPCTSTR lpszLayoutText);
前一个参数
lpszIMEFileName
是
“.ime”
文件的路径,
Win9x
为
“\System”
下,
WinNT/2000
为
“\System32”
下。后一个参数
lpszLayoutText
是输入法的明称。如
HKL
MyIme=ImmInstallIME(“Windows\system\3jaja.ime”,“3++
输入法
“);
如果
MyIme
不返回
NULL
,则调用成功。
4.“.ime”
文件的实现
程序中的输出函数(必须)即文件
“.def”
中的函数,以下为函数的名称和原形,部分函数给
出了原函数,
希望对你能有所帮助。
Cpp
代码
初始化输入法函数
BOOL
WINAPI ImeInquire(LPIMEINFO lpImeInfo,
LPTSTR
lpszWndCls,
DWORD
lpszOptions)
{
if (!lpImeInfo)
return (FALSE);
lpImeInfo->dwPrivateDataSize = sizeof(PRIVCONTEXT);
lpImeInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | IME_PROP_CAN
DLIST_START_FROM_1 | IME_PROP_IGNORE_UPKEYS;
lpImeInfo->fdwConversionCaps = IME_CMODE_NATIVE|IME_CMODE_NATI
VE|IME_CMODE_FULLSHAPE|IME_CMODE_CHARCODE | IME_CMODE_SOF
TKBD | IME_CMODE_NOCONVERSION;
lpImeInfo->fdwSentenceCaps = 0;
lpImeInfo->fdwUICaps = UI_CAP_ROT90 | UI_CAP_SOFTKBD;
lpImeInfo->fdwSCSCaps = SCS_CAP_COMPSTR | SCS_CAP_MAKEREAD;
lpImeInfo->fdwSelectCaps = (
DWORD
)0;
lstrcpy(lpszWndCls, (
LPTSTR
)szUIClassName);
return (TRUE);
}
//
自定义汉字编码格式,未作处理。
DWORD
WINAPI ImeConversionList(HIMC hIMC,
LPCTSTR
lpszSrc,
DWORD
uB
ufLen,
UINT
uFlag)
{
return (0);
}
//
设置输入法状态函数,如光标跟随等
BOOL
WINAPI ImeConfigure(
HKL
hKL,
HWND
hAppWnd,
DWORD
dwMode,
LPV
OID
lpData)
{
switch (dwMode)
{
case IME_CONFIG_GENERAL:
DialogBox(hInst, MAKEINTRESOURCE(SETIME), (
HWND
)hAppWnd, (DLG
PROC)ImeSetDlgProc);
break;
default:
return (FALSE);
break;
}
return (TRUE);
}
//
退出
BOOL
WINAPI ImeDestroy(
UINT
uReserved)
{
if (uReserved)
return (FALSE);
return (TRUE);
}
//
应用接口函数
LRESULT
WINAPI ImeEscape(HIMC hIMC,
UINT
uSubFunc,
LPVOID
lpData)
{
LRESULT
lRet;
switch (uSubFunc)
{
case IME_ESC_QUERY_SUPPORT:
if ( lpData == NULL )
return FALSE;
switch (*(LPUINT)lpData)
{
case IME_ESC_QUERY_SUPPORT:
case IME_ESC_MAX_KEY:
case IME_ESC_IME_NAME:
case IME_ESC_GETHELPFILENAME:
return (TRUE);
case IME_ESC_SEQUENCE_TO_INTERNAL:
case IME_ESC_GET_EUDC_DICTIONARY:
case IME_ESC_SET_EUDC_DICTIONARY:
case IME_INPUTKEYTOSEQUENCE:
return (FALSE);
default:
return (FALSE);
}
break;
case IME_ESC_SEQUENCE_TO_INTERNAL:
case IME_ESC_GET_EUDC_DICTIONARY:
case IME_ESC_SET_EUDC_DICTIONARY:
case IME_INPUTKEYTOSEQUENCE:
return (FALSE);
case IME_ESC_MAX_KEY:
return ((
WORD
) 4);
case IME_ESC_GETHELPFILENAME:
{
TCHAR
szIMEGUDHlpName[MAXSTRLEN];
if (lpData == NULL )
return FALSE;
szIMEGUDHlpName[0] = 0;
GetWindowsDirectory((
LPTSTR
)szIMEGUDHlpName, MAXSTRLEN);
lstrcat((
LPTSTR
)szIMEGUDHlpName, TEXT(“file://HELP//3JaJa.hlp”));
lstrcpy((
char
*)lpData, (
char
*)szIMEGUDHlpName);
return TRUE;
}
default:
return (FALSE);
}
return (lRet);
}
//
启动输入法设置功能
BOOL
WINAPI ImeSelect(HIMC hIMC,
BOOL
fSelect
)
{
LPINPUTCONTEXT lpIMC;
BOOL
fRet;
if (!hIMC)
return (FALSE);
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
return (FALSE);
fRet = Select(hIMC, lpIMC, fSelect);
ImmUnlockIMC(hIMC);
return (fRet);
}
//
设置输入活动状态
BOOL
WINAPI ImeSetActiveContext(HIMC hIMC,
BOOL
fOn)
{
if (fOn&&hIMC)
{
LPINPUTCONTEXT lpIMC;
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
return (FALSE);
InitContext(lpIMC);
ImmUnlockIMC(hIMC);
}
return (TRUE);
}
//
用户按键处理函数,例如中英文状态,返回
FALSE
为英文状态,按键不作处
理。
BOOL
WINAPI ImeProcessKey(HIMC hIMC,
UINT
uVirtKey,
LPARAM
lParam,C
ONST
LPBYTE
lpbKeyState);
//
输入法编码字符处理。
BOOL
WINAPI ImeSetCompositionString(HIMC hIMC,
DWORD
dwIndex,
LPVOI
D
lpComp,
DWORD
dwCompLen,
LPVOID
lpRead,
DWORD
dwReadLen);
将用户按键转换为汉字编码
UINT
WINAPI ImeToAsciiEx(
UINT
uVirtKey,
UINT
uScanCode,CONST
LPBYTE
lpbKeyState,LPTRANSMSGLIST lpTransBuf,
UINT
fuState,HIMC hIMC)
//
处理
IME
消息函数
BOOL
WINAPI NotifyIME(HIMC hIMC,
DWORD
dwAction,
DWORD
dwIndex,
DW
ORD
dwValue);
自定义汉字编码格式,未作处理。
BOOL
WINAPI ImeRegisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LP
CTSTR
lpszString)
{
return (FALSE);
}
//
自定义汉字编码格式,未作处理。
BOOL
WINAPI ImeUnregisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
L
PCTSTR
lpszString)
{
return (FALSE);
}
//
自定义汉字编码格式,未作处理。
UINT
WINAPI ImeGetRegisterWordStyle(
UINT
nItem,LPSTYLEBUF lpStyleBuf)
{
return (FALSE);
}
//
自定义汉字编码格式,未作处理。
UINT
WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC lpfnRegi
sterWordEnumProc,
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszStr
ing,
LPVOID
lpData)
{
return (FALSE);
}
//UI
窗口过程
LRESULT
CALLBACK UIWndProc(
HWND
hUIWnd,
UINT
uMsg,
WPARAM
w
Param,
LPARAM
lParam)
{
switch (uMsg)
{
case WM_CREATE:
CreateUIWindow(hUIWnd);
break;
case WM_DESTROY:
DestroyUIWindow(hUIWnd);
break;
case WM_IME_STARTCOMPOSITION:
......
}
}
//
状态窗口过程
LRESULT
CALLBACK StatusWndProc(
HWND
hStatusWnd,
UINT
uMsg,
WPAR
AM
wParam,
LPARAM
lParam);
编码窗口过程
LRESULT
CALLBACK CompWndProc(
HWND
hCompWnd,
UINT
uMsg,
WPAR
AM
wParam,
LPARAM
lParam);
侯选汉字窗口过程
LRESULT
CALLBACK CandWndProc(
HWND
hCandWnd,
UINT
uMsg,
WPARA
M
wParam,
LPARAM
lParam);
5.
头文件及链接文件
记得要定义
IMM32.h
及链接文件
IMM32.lib
。至于有关
“ .ime”
程序中必须用到的结构,
大家可参考
MSDN
中的有关文档。
二、常用函数
BOOL WINAPI ImmGenerateMessage( //
将汉字串法发送到与当前输入法相关联的应用软
件中
HIMC hIMC
);//
成功为
TRUE
,否则为
FALSE
LRESULT WINAPI ImmRequestMessage( //
向应用程序发送
WM_IME_REQUEST
消息
HIMC hIMC, //
与当前输入法相关联的应用软件的句柄
WPARAM wParam, //
与
WM_IME_REQUEST
相关的
wP
LPARAM lParam //
与
WM_IME_REQUEST
相关的
LP
);
LPINPUTCONTEXT WINAPI ImmLockIMC( //
获取当前
IMC
的
INPUTCONTEXT
结构信
息,增加
IMC
计数器
HIMC hIMC
);//
成功返回
INPUTCONTEXT
结构指针,否则为
NULL
BOOL WINAPI ImmUnlockIMC( //
释放
IMC
计数器
HIMC hIMC );//
返回
:
如果
IMC
计数器被减少到
0
了
,
返回
FALSE,
否则为
TRUE.
注意
:ImmLockIMC
与
ImmUnlockIMC
必须成对出现
,
必须是相同的
HIMC
HIMCC WINAPI ImmGetIMCLockCount( //
取计数器值
HIMC hIMC );//
如果成功返回
HIMC
的计数器值,否则为
NULL.
HIMCC WINAPI ImmCreateIMCC( //
创建
INPUTCONTEXT
结构的一个成员
DWORD dwSize //
成员的缓冲区长度
);//
如果成功返回
IMC
的成员句柄,否则为
NULL
HIMCC WINAPI ImmDestroyIMCC( //
删除
IMC
成员缓冲区
HIMCC hIMCC
);//
如果成功返回
NULL
,否则等于该
HIMCC.
LPVOID WINAPI ImmLockIMCC( //
取
IMCC
缓冲地址,同时使
IMCC
的计数器值增加
HIMCC hIMCC );
BOOL WINAPI ImmUnlockIMCC( //
递减
IMCC
计数器
HIMCC hIMCC );//
如果
IMCC
的计数器值为零,则返回
FALSE
,否则为
TRUE.
10
、
HIMCC WINAPI ImmReSizeIMCC( //
重新设置
IMC
的成员的缓冲区大小
HIMCC hIMCC, //IMC
的成员句柄
DWORD dwSize //
新缓冲区大小
);//
如果成功,返回新的
HIMCC
,否则为
NULL.
DWORD WINAPI ImmGetIMCCSize( //
取
IMC
成员的缓冲区大小
HIMCC hIMCC );//
返回
IMC
成员的缓冲区大小
12
、
DWORD WINAPI ImmGetIMCCLockCount( //
返回
IMC
计数器值
HIMCC hIMCC
);//
成功返回该
IMCC
的计数器值,否则为
0
BOOL WINAPI ImmGetHotKey( //
取输入法状态键,该函数供控制面板使用
DWORD dwHotKeyID,
LPUINT lpuModifiers,
LPUINT lpuVKey,
LPHKL lphKL
)
BOOL WINAPI ImmSetHotKey( //
设置输入法的热键
DWORD dwHotKeyID,
UINT uModifiers,
UINT uVKey,
hKL hKL
)
HWND WINAPI ImmCreateSoftKeyboard( //
产生一个软键盘
UINT uType, //
软件盘上的键码含义的定义方式
UINT hOwner, //
该输入法的
UI
窗口
int x, //x
坐标
int y //y
坐标
);//
成功返回软键盘的窗口句柄
BOOL WINAPI ImmDestroySoftKeyboard( //
销毁软键盘
HWND hSoftKbdWnd //
软键盘窗口句柄
);//
成功为
TRUE,
法哦则为
FALSE.
17
、
BOOL WINAPI ImmShowSoftKeyboard( //
显示或隐藏软键盘
HWND hSoftKbdWnd, //
软键盘窗口句柄
int nCmdShow //SW_HIDE=
隐藏,
SW_SHOWNOACTIVATE=
显示
);//
如构成功返回
TRUE.
否则为
FALSE.
二、
IME
文件中的常用结构
1
、
IMEINFOstruct tagIMEInfo { //
输入法的接口信息
DWORD dwPrivateDataSize;//
用户设计的数据结构的字节数
DWORD fdwProperty; //
输入法对键盘事件的相应特性
DWORD fdwConversionCaps;//
当前输入法具有的功能特性
,
如有软键盘、标点、中西文切
换等功能
DWORD fdwSentenceCaps;
DWORD fdwUICaps; //
用户界面能力:支持软键盘等
DWORD fdwSCSCaps; //
用户设置编码串的能力
DWORD fdwSelectCaps; //
输入法切换时是否使用以前输入法的模式
} IIMEINFO;
2
、
COMPOSITIONSTR
用于编码管理
typedef struct tagCOMPOSITIONSTR {
DWORD dwSize; //
当前编码信息需要的存储空间
DWORD dwCompReadAttrLen;
//
读入的编码属性长度
DWORD dwCompReadAttrOffset; //
读入的编码的位置
DWORD dwCompReadClsLen;
//
读入的子串长度
DWORD dwCompReadClsOffset; //
读入的子串的位置
DWORD dwCompReadStrLen;
//
读入的编码长度
DWORD dwCompReadStrOffset; //
读入的编码的位置
DWORD dwCompAttrLen; //
编码属性长度
DWORD dwCompAttrOffset; //
编码属性在内存的位置
DWORD dwCompClsLen; //
编码子串长度
DWORD dwCompClsOffset; //
编码子串在内存的位置
DWORD dwCompStrLen; //
编码串长度
DWORD dwCompStrOffset; //
编码串在内存的位置
DWORD dwCursorPos; //
当前光标位置
DWORD dwDeltaStart; //
被修改编码的位置
DWORD dwResultReadClsLen; //
读入结果子串长度
DWORD dwResultReadClsOffset; //
读入结果子串在内存的位置
DWORD dwResultReadStrLen; //
读入的编码长度
DWORD dwResultReadStrOffset;
//
读入的编码在内存的位置
DWORD dwResultClsLen; //
结果子串长度
DWORD dwResultClsOffset; //
结果子串在内存的位置
DWORD dwResultStrLen; //
结果串长度
DWORD dwResultStrOffset; //
结果串在内存的位置
DWORD dwPrivateSize; //
用户自定义数据长度
DWORD dwPrivateOffset; //
用户自定义数据在内存的位置
} COMPOSITIONSTR;
3
、
CANDIDATEINFO
用于编码选择管理
typedef struct tagCANDIDATEINFO {
DWORD dwSize; //
数据所占内存大小
DWORD dwCount; //
数据个数
DWORD dwOffset[32]; //
各个编码列表的内存位置
DWORD dwPrivateSize; //
自定义数据尺寸
DWORD dwPrivateOffset; //
缓冲区位置
} CANDIDATEINFO;
4
、
GUIDELINE
typedef struct tagGUIDELINE {
DWORD dwSize;
DWORD dwLevel;
DWORD dwIndex;
DWORD dwStrLen;
DWORD dwStrOffset;
DWORD dwPrivateSize;
DWORD dwPrivateOffset;
} GUIDELINE;
5
、
CANDIDATELIST
编码选择列表信息
typedef struct tagCANDIDATELIST {
DWORD dwSize; //
用字节表示的内存大小
DWORD dwStyle; //
列表串的取值方式
DWORD dwCount; //
当前列表个数
DWORD dwSelection; //
当前选择的列表序号
DWORD dwPageStart; //
在列表窗口中所显示的列表的起始序号
DWORD dwPageSize; //
一页显示的列表个数
DWORD dwOffset[]; //
列表数据存放区地址
} CANDIDATELIST;
6
、
COMPOSITIONFORM
窗口位置、大小信息:
typedef tagCOMPOSITIONFORM {
DWORD dwStyle; //
管理窗口方式
POINT ptCurrentPos; //
给定坐标
RECT rcArea;
}COMPOSITIONFORM;
7
、
CANDIDATEFORM
列表窗口信息
typedef tagCANDIDATEFORM {
DWORD dwIndex; //
列表窗口序号
DWORD dwStyle; //
属性:
POINT ptCurrentPos; //
坐标位置
REC rcArea;
} CANDIDATEFORM;
12
、
INPUTCONTEXT IMC
数据存放区
typedef struct tagINPUTCONTEXT {
HWND hWnd; //
使用该
IMC
的窗口
BOOL fOpen; //IME
的打开与关闭状态
POINT ptStatusWndPos; //
状态窗口的位置
POINT ptSoftKbdPos; //
软键盘的位置
DWORD fdwConversion; //IME
状态
(
活动、不活动,全角等)
DWORD fdwSentence; //
编码方式
union {
代码编译完毕
标签:des style http io ar os 使用 sp for
原文地址:http://my.oschina.net/bigfool007139/blog/353390