以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  IME输入法编程  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=46741)


--  作者:卷积内核
--  发布时间:5/11/2007 4:41:00 PM

--  IME输入法编程
第一章 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:盘下):

C:\Dumpbin c:\windows\system\winpy.ime

Microsoft (R) COFF Binary File Dumper Version 6.00.8168

Copyright (C) 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 number of names     // 对应19个名称 

ordinal hint RVA name

1 0 0000A010 CandWndProc  //"选择汉字窗口"注册函数

2 1 0000E750 CompWndProc  //"输入编码窗口"注册函数

3 2 0000FB50 ImeConfigure  //配置当前ime参数函数 

4 3 0000FEC0 ImeConversionList//将字符或字符串转换成目标字符

5 4 0000FFA0 ImeDestroy   //退出当前使用的IME

6 5 000030D0 ImeEnumRegisterWord

7 6 0000FFB0 ImeEscape //应用软件访问输入法的接口函数.

8 7 00003080 ImeGetRegisterWordStyle

9 8 0000E9A0 ImeInquire      //启动并初始化当前IME输入法

10 9 0000A800 ImeProcessKey    //IME输入键盘事件管理函数

11 A 00002C20 ImeRegisterWord //向输入法字典注册字符串

12 B 000109A0 ImeSelect //启动当前IME输入法

13 C 000109E0 ImeSetActiveContext //设置当前的输入处于活动状态.

14 D 0000C850 ImeSetCompositionString 由应用程序设置输入法编码

15 E 0000AEE0 ImeToAsciiEx    //将输入的键盘事件转换为汉字编码事件

16 F 00002F40 ImeUnregisterWord //删除被注册的字符串.

17 10 0000CA90 NotifyIME   //IME事件管理函数

18 11 00005160 StatusWndProc //状态窗口注册函数

19 12 00002350 UIWndProc   //用户界面接口函数

Summary

5000 .ShareDa

7000 .data

2000 .idata

1000 .rdata

3000 .reloc

5000 .rsrc

2000 .sgroup

18000 .text

从上述可以看出,IME程序共有19个出口函数组成,每一个函数都有特定的格式,它们担负着与windows

系统传递信息的作用,这些函数是供Windows系统调用的。

三、输入法的函数简介

下面我们将介绍上述各个函数的功能及接口格式。

1. BOOL ImeInquire( //初始化IME

LPIMEINFO lpIMEInfo, //用于初始化该输入法的结构地址

LPTSTR lpszWndClass, //当前输入法的名称

LPCTSTR或者dword lpszData //系统信息,9X系列值为0,NT/2000下有实际值

)

如果该函数初始化成功,返回TURE,否则为FALSE

用户应该搞清楚IMEINFO结构,特关系着你设计的输入法是否成功.有关该结构请看"结构"一章.

2.DWORD IMEConversionList( // 将某字符或字符串转换成目标字符串

HIMC hIMC, // 与当前输入法相关的应用程序句柄

LPCTSTRlpSrc, // 要转换的字符串 (也可能是结果串,可由uFlag指定)

LPCANDIDATELIST lpDst, /// 转换后的字符串(也可能是源串,可由uFlag指定)

DWORD dwBufLen, //转换后有几个字符

UINT uFlag //指定结果的存放位置

)

如果成功,返回转换后的字符串长度

3.BOOL ImeConfigure( //用户设置输入法接口

HKL hKL, //当前输入法句柄

HWND hWnd, //配置窗口的父窗口

DWORD dwMode, //配置什么

LPVOID lpData //用户设置的数据

)

该函数的功能是提供给输入法使用者一个可以更改某些隐含设置的能力.

如果你用过别人的输入法,其中的"配置输入法..."功能既是也!

对于一个初写输入法的人,可以不予理它.

4.BOOL ImeDestroy( //关闭当前输入法

UINT uReserved //无用 (0)

)

成功返回TURE,否则为FALSE

5.LRESULT ImeEscape( //用户软件访问输入法内部信息的接口

HIMC hIMC, //当前的应用程序句柄

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)

//=IME_ESC_PRIVATE_HOTKEY(w95下不可用)

LPVOID lpData //当前功能所需的数据

)

如果失败,返回0,否则有个功能决定

有时,人们可以用此函数怀区输入法的名称、帮助文件名称等。当然,我们可以不提供这些功能。

 

6、BOOL ImeSetActiveContext( //激活或搁置当前的输入法

HIMC hIMC, //当前用户程序句柄

BOOL fFlag //激活或搁置:=TRUE 激活 =FALSE 搁置

)

成功返回TRUE,否则为FALSE

7、BOOL ImeProcessKey( //处理应用程序传入的所有击键事件,监测是否是当前输入法所需的

HIMC hIMC, //应用程序句柄

UINT uVirKey, //需处理的虚键

DWORD lParam, //击键消息参数

CONST LPBYTE lpbKeyState //当前键盘状态(256字节)

)

如果此键是该输入法需要的,则返回TRUE,否则为FALSE

只有返回true的击键,IME才去处理

8、BOOL NotifyIME( //输入法选择窗口状态管理函数:

HIMC hIMC, //当前的应用程序句柄

DWORD dwAction, //状态值

DWORD dwIndex, //与状态值有关的序号

DWORD dwValue //与状态值有关的值

)

状态值说明:

=NI_OPENCANDIDATE 打开编码选择窗口

=NI_CLOSECANDIDATE 关闭当前的编码选择窗

=NI_SELECTCANDIDATESTR 选摘编码

此时:dwIndex 被选择的编码列表序号.

dwValue 被选中的编码在当前的编码列表中的序号

=NI_CHANGECANDIDATELIST 改变当前的编码列表(按pageup等键操作)

此时:dwIndex 被选择的编码列表序号.

dwValue 不用

=NI_SETCANDIDATE_PAGESTART 设置编码开始页号

此时: dwIndex 被改变的编码列表序号

dwValue 新页的开始序号.

=NI_SETCANDIDATE_PAGESIZE 改变编码列表页的大小

此时:dwIndex 当前编码页序号

dwValue 新的页大小

=NI_CONTEXTUPDATED 更新应用程序的信息的输入法的信息:移动位置,设置模式,设置编码窗口,字体。

此时:dwIndex 只用于 dwValue=IMC_SETCONVERSIONMODE, IMC_SETSENTENCEMODE

dwValue 可取由 WM_IME_CONTROL 发送的下列值:

IMC_SETCANDIDATEPOS

IMC_SETCOMPOSITIONFONT

IMC_SETCOMPOSITIONWINDOW

IMC_SETCONVERSIONMODE

IMC_SETSENTENCEMODE

IMC_SETOPENSTATUS

=NI_COMPOSITIONSTR 改变编码窗口中的编码

此时:dwIndex 取下列值:CPS_COMPLETE 完成编码转换

CPS_CONVERT 转换编码

CPS_REVERT 取消当前的编码

CPS_CANCEL 清除编码,并关闭编码窗

dwValue 不用

此函数成功,返回TRUE,否则为FALSE

9、BOOL ImeSelect( //初始化输入法

HIMC hIMC, //当前应用程序句柄

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)给系统,

HIMC hIMC, //当前的应用程序句柄

DWORD dwIndex, //设置此函数功能

//=SCS_SETSTR

//=SCS_CHANGEATTR

//=SCS_CHANGECLAUSE

//= SCS_QUERYRECONVERTSTRING

//=SCS_RECONVERTSTRING

//=SCS_SETRECONVERTSTRING

LPCVOID lpComp, //编码数据区

DWORD dwCompLen, //编码数据区长度

LPCVOID lpRead, //读入的编码数据

DWORD dwReadLen //读入的编码数据长度

11、UINT ImeToAsciiEx( //转换编码称汉字(串)

UINT uVirKey, //虚键

UINT uScanCode, //扫描码

CONST LPBYTE lpbKeyState, //用户定义的键盘状态

LPDWORD lpdwTransBuf, //转换后的数据存放区

UINT fuState, //活动菜单标志

HIMC hIMC //当前的应用程序句柄

)

返回:返回值表示有几个消息,可理解为:本编码对应的汉字串有几个汉字组成(当然,这并不相等)。

12、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

)


--  作者:卷积内核
--  发布时间:5/11/2007 4:41:00 PM

--  
四.ime的版本信息(与普通DLL的区别)

VS_VERSION_INFO VERSIONINFO 代表字符 含义

FILEVERSION 4,0,0,950 //4.00.950 95版

PRODUCTVERSION 4,0,0,950 //4.00.950 95版

FILEFLAGSMASK 0x3fL

FILEFLAGS 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"

VALUE "FileDes cription", "唐码输入法 版本1.0\0"

VALUE "FileVersion", "4.00.950\0"

VALUE "InternalName", "唐码输入法 版本1.0\0"

VALUE "LegalCopyright", "Copyright (C) 唐码软件开发工作室 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


--  作者:卷积内核
--  发布时间:5/11/2007 4:41:00 PM

--  
第二章 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函数清单

ImmGetCompositionWindow //取编码窗口信息

ImmSetCompositionWindow //设置编码窗口信息

ImmGetCandidateWindow //取选择窗口信息

ImmSetCandidateWindow //设置选择窗口信息

ImmGetCompositionString //取编码窗口的某一信息

ImmSetCompositionString //设置编码窗口的某一信息

ImmGetCompositionFont //取编码字体

ImmSetCompositionFont //设置编码字体

ImmGetNumCandidateList //取选择区中编码数

ImmGetCandidateList //取选择区中编码

ImmGetGuideLine

ImmGetConversionStatus //取当前输入法的状态(ACSII,SHAPE,FULL等)

ImmGetConversionList //重新获得选择区转换表

ImmGetOpenStatus //取输入法打开属性

ImmSetConversionStatus //设置输入法状态

ImmSetOpenStatus //设置输入法打开状态

ImmNotifyIME //通报IME,输入法状态被改变

ImmGenerateMessage //将我们的汉字串法发送到与当前输入法相关联的应用软件中

ImmRequestMessage //向应用程序发送WM_IME_REQUEST

ImmLockIMC //获取当前IMC的INPUTCONTEXT结构信息,增加IMC 计数器

ImmUnlockIMC //释放IMC计数器

ImmGetIMCLockCount //取计数器值

ImmCreateIMCC //创建INPUTCONTEXT结构的一个成员

ImmDestroyIMCC //删除IMC成员缓冲区

ImmLockIMCC //取IMCC缓冲地址,同时使IMCC的计数器值增加

ImmUnlockIMCC //递减IMCC计数器

ImmReSizeIMCC //重新设置IMC的成员的缓冲区大小

ImmGetIMCCSize //取IMC成员的缓冲区大小

ImmGetIMCCLockCount //返回IMC计数器值

ImmGetHotKey //取输入法状态键,该函数供控制面板使用

ImmSetHotKey //设置输入法的热键

ImmCreateSoftKeyboard //产生一个软键盘

ImmDestroySoftKeyboard //销毁软键盘

ImmShowSoftKeyboard //显示或隐藏软键盘

二、IMM函数使用格式说明

1、BOOL WINAPI ImmGenerateMessage( //将我们的汉字串法发送到与当前输入法相关联的应用软件中

HIMC hIMC //与当前输入法相关联的应用软件的句柄,

//该结构的hMsgBuf项即为汉字串消息

)

成功为TRUE,否则为FALSE

2、LRESULT WINAPI ImmRequestMessage( //向应用程序发送WM_IME_REQUEST

//只是用于w98及w2000

HIMC 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 计数器

HIMC hIMC //当前应用程序句柄

)

成功返回INPUTCONTEXT 结构指针,否则为NULL

4、BOOL WINAPI ImmUnlockIMC( //释放IMC计数器

HIMC hIMC //当前应用程序句柄

)

返回:如果IMC计数器被减少到0了,返回FALSE,否则为TRUE.

注意:ImmLockIMC与ImmUnlockIMC必须成对出现,必须是相同的HIMC

5、HIMCC WINAPI ImmGetIMCLockCount( //取计数器值

HIMC hIMC //当前应用程序句柄

)

如果成功返回HIMC的计数器值,否则为NULL.

6、HIMCC WINAPI ImmCreateIMCC( //创建INPUTCONTEXT结构的一个成员

DWORD dwSize //成员的缓冲区长度

)

如果成功返回IMC的成员句柄,否则为NULL

7、HIMCC WINAPI ImmDestroyIMCC( //删除IMC成员缓冲区

HIMCC hIMCC //被删除的IMC的成员

)

如果成功返回NULL,否则等于该HIMCC.

8、LPVOID WINAPI ImmLockIMCC( //取IMCC缓冲地址,同时使IMCC的计数器值增加

HIMCC hIMCC //IMC成员句柄

)

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计数器

HIMCC hIMCC //IMC成员句柄

)

如果IMCC的计数器值为零,则返回 FALSE,否则为TRUE.

10、HIMCC WINAPI ImmReSizeIMCC( //重新设置IMC的成员的缓冲区大小

HIMCC hIMCC, //IMC的成员句柄

DWORD dwSize //新缓冲区大小

)

如果成功,返回新的HIMCC,否则为 NULL.

11、DWORD WINAPI ImmGetIMCCSize( //取IMC成员的缓冲区大小

HIMCC hIMCC //IMC成员句柄

)

返回IMC成员的缓冲区大小

12、DWORD WINAPI ImmGetIMCCLockCount( //返回IMC计数器值

HIMCC hIMCC //IMC成员的句柄

)

成功返回该IMCC的计数器值,否则为0

13、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 //定位坐标

)

成功返回软键盘的窗口句柄

16、BOOL WINAPI ImmDestroySoftKeyboard( //销毁软键盘

HWND hSoftKbdWnd //软年盘窗口句柄

)

成功为TRUE,法哦则为FALSE.

17、BOOL WINAPI ImmShowSoftKeyboard( //显示或隐藏软键盘

HWND hSoftKbdWnd, //软年盘窗口句柄

int nCmdShow //窗口状态=SW_HIDE 表示隐藏,=SW_SHOWNOACTIVATE表示显示

)

如构成功返回 TRUE. 否则为 FALSE.


--  作者:卷积内核
--  发布时间:5/11/2007 4:42:00 PM

--  
第三章 ime文件中必须使用的结构

前二章我们讲述了ime和imm函数,二者之间是靠下列结构通讯的。

1、IMEINFO

struct tagIMEInfo { //输入法的接口信息 用于ImeInquire函数中

DWORD dwPrivateDataSize;//用户设计的数据结构的字节数

DWORD fdwProperty; //输入法对键盘事件的相应特性

//其中其高字可为下列字节位的组合:

//=IME_PROP_AT_CARET 转换窗口是否放置在需插入字符的位置

//=IME_PROP_SPECIAL_UI 该输入法具有特殊用户接口

//=IME_PROP_CANDLIST_START_FROM_1 输入法的选择窗口中汉字串的起始序号为1

//=IME_PROP_UNICODE 支持UNICODE字符

//其中其低字可为下列字节位的组合:

//=IME_PROP_END_UNLOAD

//=IME_PROP_KBD_CHAR_FIRST 首先由键盘转换字符

//=IME_PORP_NEED_ALTKEY 将ALT键盘事件传送到IME输入法内

//=IME_PROP_IGNORE_UPKEYS 禁止上位键事件进入输入法内

//=IME_PROP_COMPLETE_ON_UNSELECT 当关闭输入法时,完成编码的转换

// 用于 W98及2000 中

DWORD fdwConversionCaps;//当前输入法具有的功能特性,如有软键、标点、中西文切换等功能

//=IME_CMODE_NATIVE 设置活动模式

//=IME_CMODE_FULLSHAPE 设置全角模式

//=IME_CMODE_CHARCODE 设置为字符模式

//=IME_CMODE_SOFTKBD //设置软键盘模式

//=IME_CMODE_NOCONVERSION //不支持模式变换

//=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 用于编码管理

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; // 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; // 列表串的取值方式

//=IME_CAND_UNKNOWN 列表数据的格式无定义

//=IME_CAND_READ 读到什么数据即为什么数据,一般我们使用该属性

//=IME_CAND_CODE 如果dwCount=1,dwOffset不是地址,而是实际数据,

// >1 dwOffset 表示地址

//=IME_CAND_MEANING

//=IME_CAND_RADICAL

//=IME_CAND_STROKES

DWORD dwCount; // 当前列表个数

DWORD dwSelection; // 当前选择的列表序号

DWORD dwPageStart; // 在列表窗口中所显示的列表的起始序号(上下翻页时用)

DWORD dwPageSize; // 一页显示的列表个数

DWORD dwOffset[]; // 列表数据存放区地址:[阿];[大]。。。。

} CANDIDATELIST;

6、COMPOSITIONFORM

typedef tagCOMPOSITIONFORM { //窗口位置、大小信息:

//由IMC_SETCOMPOSITIONWINDOW和IMC_SETCANDIDATEPOS消息使用

DWORD dwStyle; //管理窗口方式

//=CFS_DEFAULT 将编码窗口显示到隐含的位置

//=CFS_FORCE_POSITION // 以给定的坐标显示窗口,不受IME控制

//=CFS_POINT // 以给定的坐标显示窗口,受IME控制

//=CFS_RECT //以给定的大小显示窗口

POINT ptCurrentPos; //给定坐标

RECT rcArea; //给定窗口的小

}COMPOSITIONFORM;

7、CANDIDATEFORM

The CANDIDATEFORM structure is used for IMC_GETCANDIDATEPOS and

IMC_SETCANDIDATEPOS messages.

typedef tagCANDIDATEFORM { //列表窗口信息

//由IMC_GETCANDIDATEPOS和IMC_SETCANDIDATEPOS消息处理

DWORD dwIndex; //列表窗口序号

DWORD dwStyle; //属性:

//=CFS_CANDIDATEPOS 指定显示位置

//=CFS_EXCLUDE 不可显示

//=CFS_DEFAULT 根据需要显示

POINT ptCurrentPos; //坐标位置

REC rcArea; //不可显示区

} CANDIDATEFORM;

8、STYLEBUF

typedef struct tagSTYLEBUF { //注册字结构

DWORD dwStyle;

TCHAR szDes cription[32]

} STYLEBUF;

9、SOFTKBDDATA

typedef struct tagSOFTKBDDATA { //软键盘中各键对应的汉字

UINT uCount; //键码数组个数(可以为1,2,当区分SHIFT键时为2,即:一组带SHIFT,一组不带SHIFT)

WORD wCode[][256] //对应的键码数据

} SOFTKBDDATA;

10、RECONVERTSTRING

typedef struct _tagRECONVERTSTRING { //用于W98和2000

DWOPD dwSize;

DWORD dwVersion;

DWORD dwStrLen;

DWORD dwStrOffset;

DWORD dwCompStrLen;

DWORD dwCompStrOffset;

DWORD dwTargetStrLen;

DWORD dwTargetStrOffset;

} RECONVERTSTRING;

11、IMEMENUITEMINFO

typedef _tagIMEMENUITEMINFO { //输入法菜单结构,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的打开与关闭状态

POINT ptStatusWndPos; //状态窗口的位置

POINT ptSoftKbdPos; //软键盘的位置

DWORD fdwConversion; //IME状态(活动、不活动,全角等)

DWORD fdwSentence; //编码方式

union {

LOGFONTA A;

LOGFONTW W;

} lfFont; //字体

COMPOSITIONFORM cfCompForm; //编码格式结构

CANDIDATEFORM cfCandForm[4]; //列表选择结构

HIMCC hCompStr; //

HIMCC hCandInfo;

HIMCC hGuideLine

HIMCC hPrivate;

DWORD dwNumMsgBuf; //存放在hMsgBuf中的消息数

HIMCC hMsgBuf; //存放的消息,格式: [消息1] [wParam1] [lParam1] {[消息] [wParam2] [lParam2]...

//注意:我们输入的汉字串存放在这里

DWORD fdwInit //系统根据此值来初始本结构相应的信息

//=INIT_STATUSWNDPOS 初始化ptStatusWndPos

//=INIT_CONVERSION 初始化fdwConversion

//=INIT_SENTENCE 初始化fdwSentence

//=INIT_LOGFONT 初始化lfFont

//=INIT_COMPFORM 初始化cfCompForm

//=INIT_SOFTKBDPOS 初始化ptSoftKbdPos

DWORD dwReserve[3]; //将来版本扩展的信息

} INPUTCONTEXT;


--  作者:卷积内核
--  发布时间:5/11/2007 4:42:00 PM

--  
在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;

lParam = 0;

7)IMC_GETSTATUSWINDOWPOS

获取状态窗口位置

wSubMessage= IMC_GETSTATUSWINDOWPOS;

lParam = 0;

返回状态窗口坐标原点在屏幕窗口中的坐标结构POINTS。

8)IMC_SETCANDIDATEPOS

wSubMessage= IMC_SETCANDIDATEPOS;

lpCANDIDATEFORM= (LPCANDIDATEFORM) lParam;

设置列表窗口的位置.此时lParam传送的是CANDIDATEFORM结构地址。

如果此消息成功返回0,否则非零。

注意:UI窗口不接受此消息,它的管理函数是NotifyIME。

9)IMC_SETCOMPOSITONFONT

设置编码窗口的字体.此时lParam传送的是LOGFONT结构地址。

wSubMessage= IMC_SETCOMPOSITIONFONT;

lpLogFont= (LPLOGFONT) lParam;

注意:UI窗口不接受此消息,它的管理函数是NotifyIME。

10)IMC_SETCOMPOSITONWINDOW

设置编码窗口属性,此时lParam传送的是COMPOSITIONFORM结构地址。

wSubMessage= IMC_SETCOMPOSITIONWINDOW;

lpCOMPOSITIONFORM= (LPCOMPOSITIONFORM) lParam;

如果此消息成功返回0,否则非零。

注意: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;


--  作者:hulalahulala
--  发布时间:8/1/2007 9:53:00 AM

--  
大虾:
小虾问个问题,我在练习写一个IME,PC平台的,当把immdev.h加入到工程中时,LPINPUTCONTENT在编译时没问题了,但是tagCOMPOSITIONFORM结构告诉我重定义了,我在dll工程中就没有定义啊,搞不懂为什么?请大虾帮我看看
d:\\winddk\\2600\\inc\\wxp\\immdev.h(31) : error C2011: 'tagCOMPOSITIONFORM' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(38) : error C2011: 'tagCANDIDATEFORM' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(46) : error C2011: 'tagCANDIDATELIST' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(56) : error C2011: 'tagREGISTERWORDA' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(60) : error C2011: 'tagREGISTERWORDW' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(93) : error C2011: 'tagSTYLEBUFA' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(97) : error C2011: 'tagSTYLEBUFW' : 'struct' type redefinition
d:\\winddk\\2600\\inc\\wxp\\immdev.h(215) : error C2733: second C linkage of overloaded function 'ImmSetCompositionStringA' not allowed
        d:\\winddk\\2600\\inc\\wxp\\immdev.h(215) : see declaration of 'ImmSetCompositionStringA'
d:\\winddk\\2600\\inc\\wxp\\immdev.h(216) : error C2733: second C linkage of overloaded function 'ImmSetCompositionStringW' not allowed
        d:\\winddk\\2600\\inc\\wxp\\immdev.h(216) : see declaration of 'ImmSetCompositionStringW'
--  作者:火鸟
--  发布时间:8/9/2007 5:01:00 PM

--  
真正好文,顶顶顶。
--  作者:火鸟
--  发布时间:8/9/2007 5:06:00 PM

--  
卷积内核兄能否将你有的所有输入法编程资料发我一份,我正在编一个输入法,我的email是jerry.shen@cognizant.com和jerry_shen_sjf@yahoo.com.cn
--  作者:卷积内核
--  发布时间:8/11/2007 8:00:00 AM

--  
以下是引用火鸟在2007-8-9 17:06:00的发言:
卷积内核兄能否将你有的所有输入法编程资料发我一份,我正在编一个输入法,我的email是jerry.shen@cognizant.com和jerry_shen_sjf@yahoo.com.cn


不好意思,我们单位把邮箱给屏蔽了,不能发公司外的Mail,帮不了你了.有什么好资料我会放到这里的.
--  作者:火鸟
--  发布时间:8/13/2007 4:35:00 PM

--  
不好意思,我们单位把邮箱给屏蔽了,不能发公司外的Mail,帮不了你了.有什么好资料我会放到这里的.
===============
多谢卷积内核兄,你的VC资料精品不少。
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
6,699.219ms