- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
注意:我这里指的是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[uLen]=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[uLen]=0;//结尾的\0
- ImmGetCompositionString(hIMC,GCS_RESULTSTR,szCompStr,uMem);//取得结果字符串
- 把结果字符串添加到最终输出的文本里面。;
- free(szCompStr);
- }
- ImmReleaseContext(hWnd,hIMC);
- }
- return 0;
复制代码 WM_IME_ENDCOMPOSITION://打完字
这个消息需要处理,返回0即可。收到这个消息说明候选词窗口被关闭了。
最后,我把一个写好的程序发上来。
EXE下载:
GetIME.exe
(40 KB, 下载次数: 108)
源代码下载: |
|