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
)

四 .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

第二章 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.

第三章 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;

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

Windows9x系统下汉字输入法的基本原理相关推荐

  1. IME输入法编程:第一章 Windows9x系统下汉字输入法的基本原理

    IME输入法编程 第一章 Windows9x系统下汉字输入法的基本原理 Windows系统下汉字输入法实际上是将输入的标准ascii字符串按照一定的编码规则转换为汉字或汉字串,进 入到目的地. 由于应 ...

  2. Ubuntu16.04系统下汉字显示为方框解决办法

    Ubuntu16.04系统下汉字显示为方框解决办法 问题详情 打开Ubuntu系统,发现中文变方框了 问题分析 之前中文显示好好的,突然就中文变方框了.原先以为是语言的问题,后面换成了别的中文样式,发 ...

  3. 繁体系统下因输入法引起部分软件乱码

    一直以来都在用小鸭五笔,也没有发生什么意外,最后心血来潮换了Sogou五笔,起初还觉得不错,可是用着用着觉得不对劲,以前DB2的客户端软件竟无法复制中文了,全变成了乱码,自己折腾了大半天才弄明白什么回 ...

  4. ubuntu20.04系统下中文输入法的安装与使用

    目录 1.终端操作 2.Settings添加中文语言支持 3.中文输入法的使用 注意****:别装了!!搜狗输入法与物理机的ubuntu20.04不兼容,容易引发系统崩溃!! 1.终端操作 首先我们在 ...

  5. Ubuntu16.04系统下汉字显示为方框解决办法(图文详解)

    不多说,直接上干货! 问题详情 问题分析 今天一打开Ubuntu系统,竟然不支持中文显示了.开始时以为是搜狗拼音的问题,然后重装了一遍fcitx,然后用重装了一遍搜狗输入法.可是重装后问题根本没有解决 ...

  6. linux 中文五笔输入法,Linux系统下中文输入法安装与配置技巧

    今天,在LinuxSLC5.3上安装了中文输入法,过程如下: 1.安装中文字体库 yum install "font-chinese" 2.安装scim输入法 yum instal ...

  7. Linux (Ubuntu 16.04) 下 搜狗拼音输入法乱码问题的解决方法

    说明:转载请注明出处. Ubuntu系统下搜狗拼音输入法经常乱码,搜索到的解决方法大多不可用,或者只能解决一次,很快就又出现乱码的情况.博主无意间发现一个方法,经测试,90%以上的概率是可行的,只有那 ...

  8. C语言w10输入法打不出中文,Win10系统使用微软输入法打不出汉字的解决方法

    Win10系统使用微软输入法打不出汉字该如何解决?在Win10系统中,默认自带有微软拼音输入法,方便我们输入文字,但是有不少用户在打开浏览器网页的时候,使用微软拼音输入法打字的时候只显示输入的英文字母 ...

  9. Ubuntu下搜狗拼音输入法打不出汉字的解决方法

    最近Ubuntu系统下的搜狗输入法莫名出问题了,问题如下: 问题 (1)Ubuntu下,搜狗拼音输入法能启动(系统托盘处有图标),但是打不出汉字,打字时选框不正常. (2)Deepin下,搜狗输入法无 ...

最新文章

  1. 雷军的最后一次 重 大 创 业
  2. 4.14 | 学习笔记
  3. spring(5)构建 spring web 应用程序
  4. android与php使用base64加密的字符串结果不一样解决方法
  5. leetcode114. 二叉树展开为链表
  6. windows副本不是正版怎么解决_解决Windows沙盒怎么联网问题
  7. Java中的enum详细解析------Java enum 枚举还可以这么用
  8. 解决UnicodeDecodeError: 'ascii' codec can't decod...
  9. python提取数组元素_python简单获取数组元素个数的方法
  10. adb查看某个文件是否存在_android – 使用ADB检查目录是否存在,如果存在则推送文件...
  11. 数据迁移其实是很难的
  12. Freeswitch拨号响应太慢的解决办法
  13. 微软独特的数字化转型思想和方法论
  14. 网络安全和CTF相关内容
  15. JDK7及早期版本Java HotSpot 虚拟机配置选项
  16. 如何使用stripe_使用Stripe和Laravel出售下载内容
  17. Python常见web框架汇总
  18. 微村:做APP里的掌上村长
  19. Plant Simulation仿真学习——关于仿真
  20. 7-1 换硬币 (20 分)

热门文章

  1. 支付宝扫码支付示例源码
  2. java 歌词_网易云歌词爬取(java)
  3. 项目排期工具OmniPlan实用指南
  4. Ucenter的UClinet和UC_Server编码不一致无法登陆解决方法
  5. 初中计算机教案模板,初中计算机教案模板
  6. 双主动桥隔离双向DC-DC变换器(二) 基本特性
  7. 只有失去的时候,才知道它的珍贵,QQ成为不明真相的群众发泄怒火的最大牺牲品...
  8. apt安装特定版本软件
  9. 安卓APP限制截屏录屏解决方案
  10. OD破解软件找断点方法系列【2】----万能断点法(XP系统)