输入法(IME)实现原理

xiaoxiao2026-08-08  12

这篇是我看了, 还不错的技术文档。

不错还是不能很好的理解。  只是为了做参考, 等我吃透了, 我就专门写一篇这样的文档。

 

本文来自于:http://blog.sina.com.cn/s/blog_56a388c20100004u.html

 

=============================================================

 

 

一、实现原理 1.中文输入法的组成       微软 Windows 系统中输入法由程序(DLL)名称为:*.ime文件和码表文件(字典) 名称为*.mb文件组成。 2.中文输入法的界面 [img]http://wjy.hanwenhua.com/images/Projec6.gif[/img]             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”中的函数,以下为函数的名称和原形,部分函数给出了原函数, 希望对你能有所帮助。 //初始化输入法函数 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_CANDLIST_START_FROM_1|                              IME_PROP_IGNORE_UPKEYS;    lpImeInfo->fdwConversionCaps =      IME_CMODE_NATIVE|IME_CMODE_NATIVE|IME_CMODE_FULLSHAPE|IME_CMODE_CHARCODE |IME_CMODE_SOFTKBD|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 uBufLen,UINT uFlag) {      return (0); } //设置输入法状态函数,如光标跟随等 BOOL WINAPI ImeConfigure(HKL hKL,HWND hAppWnd,DWORD dwMode,LPVOID  lpData) {     switch (dwMode)    {        case IME_CONFIG_GENERAL:              DialogBox(hInst, MAKEINTRESOURCE(SETIME), (HWND)hAppWnd, (DLGPROC)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,CONST LPBYTE lpbKeyState);                 //输入法编码字符处理。 BOOL WINAPI ImeSetCompositionString(HIMC hIMC,DWORD dwIndex,LPVOID 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,DWORD dwValue);      //自定义汉字编码格式,未作处理。 BOOL WINAPI ImeRegisterWord(LPCTSTR lpszReading,DWORD dwStyle,LPCTSTR lpszString) {     return (FALSE); } //自定义汉字编码格式,未作处理。 BOOL WINAPI ImeUnregisterWord(LPCTSTR lpszReading,DWORD dwStyle,LPCTSTR lpszString) {     return (FALSE); } //自定义汉字编码格式,未作处理。 UINT WINAPI ImeGetRegisterWordStyle(UINT nItem,LPSTYLEBUF lpStyleBuf) {     return (FALSE); } //自定义汉字编码格式,未作处理。 UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,     LPCTSTR lpszReading,DWORD dwStyle,LPCTSTR lpszString,LPVOID lpData) {     return (FALSE); } //UI窗口过程 LRESULT CALLBACK UIWndProc(HWND   hUIWnd,UINT   uMsg,WPARAM wParam,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,WPARAM wParam,LPARAM lParam); //编码窗口过程 LRESULT CALLBACK CompWndProc(HWND hCompWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); //侯选汉字窗口过程 LRESULT CALLBACK CandWndProc(HWND hCandWnd,UINT uMsg,WPARAM 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 {  LOGFONTA A;  LOGFONTW W; } lfFont; //字体 COMPOSITIONFORM cfCompForm; //编码格式结构 CANDIDATEFORM cfCandForm[4]; //列表选择结构 HIMCC hCompStr;HIMCC hCandInfo; HIMCC hGuideLine HIMCC hPrivate; DWORD dwNumMsgBuf; //存放在hMsgBuf中的消息数 HIMCC hMsgBuf; //存放的消息 DWORD fdwInit //系统根据此值来初始本结构相应的信息 DWORD dwReserve[3]; //未定义 } INPUTCONTEXT;     
转载请注明原文地址: https://www.6miu.com/read-5050900.html

最新回复(0)