【输入法】C语言获取输入法候选词的方法
注意:我这里指的是Windows GUI编程。当你设计一个3D游戏的时候,如果这个游戏不能拦截输入法,你就会觉得很难受,打字的时候看不到候选词,而游戏中按了Ctrl+空格之后各种难受、各种卡。
因此对于这样的程序,它就应该学会捕获输入法的操作,自己显示候选词列表。就像LOL(英雄联盟)那样,有自己的输入法框。
这个是怎么实现的呢?很简单,处理WM_IME_开头的窗口消息就行。
WM_IME_SETCONTEXT:
这个必须处理,告诉输入法,我自己绘制候选词列表的界面。
return DefWindowProc(hWnd,WM_IME_SETCONTEXT,wp,lp&(~ISC_SHOWUIALLCANDIDATEWINDOW));
只要这个消息被这样处理了以后,输入法的候选词框就不会出来了。
WM_IME_STARTCOMPOSITION:
处理这个消息请返回0。否则输入法的候选词框会出来。
return 0;
当你开始打字,候选词框出来的那一下,就会触发WM_IME_STARTCOMPOSITION这个消息。
WM_IME_NOTIFY:
这个消息非常重要。通过处理这个消息你可以获取候选词列表。
WPARAM的值是“子消息”,需要考虑进去。当它是以下数值的时候处理它可以获得候选词列表。
IMN_OPENCANDIDATE://开始选词
IMN_SETCANDIDATEPOS://选词窗口移动
IMN_CHANGECANDIDATE://改变选词
IMN_CLOSECANDIDATE://关闭选词窗口
这些消息触发的时候,你应该调用一些API来获取候选词列表。这个时候你需要声明一个HIMC(输入法句柄)
HIMC hIMC=ImmGetContext(hWnd);//取得输入法句柄
输入法句柄在用完后需要释放。代码如下:
ImmReleaseContext(hWnd,hIMC);//释放输入法句柄
候选词是以一个结构体的形式存储的。而且这个结构体的大小是不确定的。因此你需要取得候选词结构体的大小。
DWORD dwBufLen=ImmGetCandidateList(hIMC,0,NULL,0);//取得候选词列表结构体的大小
取得了大小,你就需要分配内存来读取候选词结构体。
LPCANDIDATELIST pList=(LPCANDIDATELIST)malloc(dwBufLen);//建立结构体
然后再次调用ImmGetCandidateList取得候选词列表
ImmGetCandidateList(hIMC,0,pList,dwBufLen);//取得候选词列表
通过pList->dwSelection可以得到当前选中的候选词的序号。pList->dwCount得到候选词个数。pList->dwOffset是一个数组,它的值是候选词的位置偏移。
取得候选词字符串指针的方法:(TCHAR*)((BYTE*)pList+pList->dwOffset[候选词序号]);//取得候选词
处理这个消息后返回0。
WM_IME_COMPOSITION:
这个消息也很重要,输入法在组字的时候发送这个消息。
这个时候需要处理LPARAM,它的值是多个常数通过按位或组合出来的值,因此需要拆开处理。if(lp&CS_INSERTCHAR)//当前光标插入一个字符
{
wp是字符的值。;
if(CS_NOMOVECARET)
不移动插入符;
}
if(lp&GCS_CURSORPOS)//取得正在输入的字符串(拼音之类的)的插入符的位置
{
HIMC hIMC=ImmGetContext(hWnd);
插入符的位置=ImmGetCompositionString(hIMC,GCS_CURSORPOS,NULL,0);
ImmReleaseContext(hWnd,hIMC);
}
if(lp&GCS_COMPSTR)//取得正在输入的字符串(拼音之类的)
{
HIMC hIMC=ImmGetContext(hWnd);
UINT uLen,uMem;
TCHAR*szCompStr;
uLen=ImmGetCompositionString(hIMC,GCS_COMPSTR,NULL,0);//取得正在输入的字符串大小
szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
if(szCompStr)
{
SIZE Size;
szCompStr=0;//结尾的\0
ImmGetCompositionString(hIMC,GCS_COMPSTR,szCompStr,uMem);//取得正在输入的字符串
显示字符串szCompStr,长度为uLen;
然后记得绘制插入符;
free(szCompStr);
}
ImmReleaseContext(hWnd,hIMC);
}
if(lp&GCS_RESULTSTR)//取得结果字符串
{
HIMC hIMC=ImmGetContext(hWnd);
UINT uLen,uMem;
TCHAR*szCompStr;
uLen=ImmGetCompositionString(hIMC,GCS_RESULTSTR,NULL,0);//取得结果字符串大小
szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
if(szCompStr)
{
szCompStr=0;//结尾的\0
ImmGetCompositionString(hIMC,GCS_RESULTSTR,szCompStr,uMem);//取得结果字符串
把结果字符串添加到最终输出的文本里面。;
free(szCompStr);
}
ImmReleaseContext(hWnd,hIMC);
}
return 0;WM_IME_ENDCOMPOSITION://打完字
这个消息需要处理,返回0即可。收到这个消息说明候选词窗口被关闭了。
最后,我把一个写好的程序发上来。
EXE下载:
源代码下载:**** Hidden Message ***** 下图是运行效果
编程的过程中发现微软头文件一个拼写错误,dwIndex被写成了deIndex
请先验证邮箱 FFFFFFFE 发表于 2014-3-30 11:37
请先验证邮箱
拿这种充满诱导性质的文字来做开门钥匙是对论坛不利的。。。 正好需要这个,谢谢 这是我需要的,我可以下载吗? 可以试试这个。 szCompStr=0;//结尾的\0
这一句是有问题的,只是在本程序中碰巧可以运行。但很感谢楼主的分享。希望认识楼主。看到的话请加我扣:289七叁四32。再次感谢楼主。 dakuiz@163.com 发表于 2014-11-11 16:36
szCompStr=0;//结尾的\0
这一句是有问题的,只是在本程序中碰巧可以运行。但很感谢楼主的分享。希望认识楼 ...
szCompStr=0;//结尾的\0
这一句是没有问题的。因为
szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
这句多分配了一个字符。所以我觉得没有问题。如果你觉得不是这个原因请告知我。 有点意思。响应也挺快的。 赞啊,太强大了 楼主应该在写一篇如何获取TSF 框架输入法候选的文章~ 使用,全屏的时候需要 谢谢楼主!我一直都在疑惑这个问题,终于知道资料了 学长学长学长学长!!!我来啦 看看看看看看看看 不错不错,要的就是这个效果 支持不错 看看