在了解工作原理前,必先清楚几个概念。
以下为输入法工作原理,如果不知道工作原理,只看输入法程序,那很难理解,同时,只知道工作原理,而不清楚程序是如何实现,也无法深入理解输入法。二者相辅相成,共同参照,方可加深理解。
输入法工作原理 如下图:
以下结合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;
}