在了解工作原理前,必先清楚几个概念。
以下为输入法工作原理,如果不知道工作原理,只看输入法程序,那很难理解,同时,只知道工作原理,而不清楚程序是如何实现,也无法深入理解输入法。二者相辅相成,共同参照,方可加深理解。
输入法工作原理 如下图:
以下结合IME转换接口 分别对其说明:
输入法初始化:
ImeInquire : 刚选择某输入法时,IMM调用此函数,获得输入法相关信息,并根据用户界面类UICLASSNAME,自动创建用户界面。
ImeSelect : 打开或关闭输入法时被调用,在此函数中对输入法上下文进行初始化或恢复释放
IMM将键盘消息传递给IME:
IMM 通过IME 转换接口ImeProcessKey 将键盘消息发动到IME
此函数对键盘消息进行筛选处理,用以判断此消息是发送给IME 还是直接发送给应用程序。
如果返回TRUE 则发送给IME 否则,直接发送给应用程序
IME将键盘消息转换为相应汉字:
IME 通过ImeToAsciiEx 函数来处理ImeProcessKey 发送过来的键盘消息,并最终转换为输出的结果串
IME 将汉字以字符消息的形式返回给IMM:
IME将使用WM_IME_CHAR或 WM_IME_COMPOSITION/GCS_RESULT消息把组合好的字符发送给窗体中的应用程序。如果应用程序没有处理这些消息,DefWindowProc函数会把它们翻译成一条或多条WM_CHAR消息
示例:
MakeResultString 将转换结果保存在输入上下文中将
GenerateMessage 发送WM_IME_COMPOSITION/GCS_RESULT消息给应用程序,从而使得应用程序获得结果串
BOOL MakeResultString(BOOL fFlag) { HIMC hIMC; LPINPUTCONTEXT lpIMC = NULL; LPCOMPOSITIONSTRING lpIMECompStr = NULL; LPTSTR lpResultStr = NULL; GENEMSG GnMsg = {0}; GetIMC(&hIMC, &lpIMC); lpIMECompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr); if (fFlag) { lpResultStr = GetResultStr(); if (!lpResultStr) return FALSE; _tcscpy((LPTSTR)((LPBYTE)(lpIMECompStr) + (lpIMECompStr)->dwResultStrOffset), lpResultStr); lpIMECompStr->dwResultStrLen = _tcslen(lpResultStr); } else { *((LPTSTR)((LPBYTE)(lpIMECompStr) + (lpIMECompStr)->dwResultStrOffset)) = _T('\0'); lpIMECompStr->dwResultStrLen = 0; } InitBMStr(); InitCandStrPage(); InitCandList(); ImmUnlockIMCC(lpIMC->hCompStr); GenerateMessage(WM_IME_COMPOSITION,0,GCS_RESULTSTR); GenerateMessage(WM_IME_ENDCOMPOSITION,0,0); ImmUnlockIMC(hIMC); return TRUE; } BOOL GenerateMessage(UINT message,WPARAM wParam,LPARAM lParam) { HIMC hIMC = {0}; LPINPUTCONTEXT lpIMC = NULL; LPDWORD lpdwTransBuf = NULL; GetIMC(&hIMC, &lpIMC); if (IsWindow(lpIMC->hWnd)) { // re-allocate the memory block for the message buffer. lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(DWORD) * 3); if (!lpIMC->hMsgBuf) goto Error; // Lock the memory for the message buffer. lpdwTransBuf = (LPDWORD)ImmLockIMCC(lpIMC->hMsgBuf); if (!lpdwTransBuf) goto Error; // Set the messages that the IME wants to generate. *(lpdwTransBuf++) = message; *(lpdwTransBuf++) = wParam; *(lpdwTransBuf++) = lParam; // Set the number of the messages. (lpIMC->dwNumMsgBuf)++; // Unlock the memory for the message buffer and the Input Context. ImmUnlockIMCC(lpIMC->hMsgBuf); // Call ImmGenerateMessage function. ImmGenerateMessage(hIMC); } Error: ImmUnlockIMC(hIMC); return TRUE; }