找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 52786|回复: 89

【输入法】C语言获取输入法候选词的方法

  [复制链接]

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24225 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
发表于 2014-3-30 06:20:53 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
注意:我这里指的是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,它的值是多个常数通过按位或组合出来的值,因此需要拆开处理。
  1. if(lp&CS_INSERTCHAR)//当前光标插入一个字符
  2. {
  3.     wp是字符的值。;
  4.     if(CS_NOMOVECARET)
  5.          不移动插入符;
  6. }
  7. if(lp&GCS_CURSORPOS)//取得正在输入的字符串(拼音之类的)的插入符的位置
  8. {
  9.     HIMC hIMC=ImmGetContext(hWnd);
  10.     插入符的位置=ImmGetCompositionString(hIMC,GCS_CURSORPOS,NULL,0);
  11.     ImmReleaseContext(hWnd,hIMC);
  12. }
  13. if(lp&GCS_COMPSTR)//取得正在输入的字符串(拼音之类的)
  14. {
  15.     HIMC hIMC=ImmGetContext(hWnd);
  16.     UINT uLen,uMem;
  17.     TCHAR*szCompStr;

  18.     uLen=ImmGetCompositionString(hIMC,GCS_COMPSTR,NULL,0);//取得正在输入的字符串大小
  19.     szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
  20.     if(szCompStr)
  21.     {
  22.         SIZE Size;
  23.         szCompStr[uLen]=0;//结尾的\0
  24.         ImmGetCompositionString(hIMC,GCS_COMPSTR,szCompStr,uMem);//取得正在输入的字符串
  25.         显示字符串szCompStr,长度为uLen;
  26.         然后记得绘制插入符;
  27.         free(szCompStr);
  28.     }
  29.     ImmReleaseContext(hWnd,hIMC);
  30. }
  31. if(lp&GCS_RESULTSTR)//取得结果字符串
  32. {
  33.     HIMC hIMC=ImmGetContext(hWnd);
  34.     UINT uLen,uMem;
  35.     TCHAR*szCompStr;

  36.     uLen=ImmGetCompositionString(hIMC,GCS_RESULTSTR,NULL,0);//取得结果字符串大小
  37.     szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
  38.     if(szCompStr)
  39.     {
  40.         szCompStr[uLen]=0;//结尾的\0
  41.         ImmGetCompositionString(hIMC,GCS_RESULTSTR,szCompStr,uMem);//取得结果字符串
  42.         把结果字符串添加到最终输出的文本里面。;
  43.         free(szCompStr);
  44.     }
  45.     ImmReleaseContext(hWnd,hIMC);
  46. }
  47. return 0;
复制代码
WM_IME_ENDCOMPOSITION://打完字
这个消息需要处理,返回0即可。收到这个消息说明候选词窗口被关闭了。
最后,我把一个写好的程序发上来。
EXE下载:
GetIME.exe (40 KB, 下载次数: 108)
源代码下载:
游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

回复

使用道具 举报

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24225 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
 楼主| 发表于 2014-3-30 06:37:52 | 显示全部楼层
下图是运行效果
20140330063512.PNG
编程的过程中发现微软头文件一个拼写错误,dwIndex被写成了deIndex
deIndex.PNG
回复 赞! 靠!

使用道具 举报

5

主题

43

回帖

197

积分

用户组: 小·技术宅

UID
167
精华
0
威望
3 点
宅币
132 个
贡献
11 次
宅之契约
0 份
在线时间
30 小时
注册时间
2014-3-30
发表于 2014-3-30 19:37:52 | 显示全部楼层
请先验证邮箱
回复 赞! 靠!

使用道具 举报

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24225 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
 楼主| 发表于 2014-3-30 19:43:38 | 显示全部楼层

拿这种充满诱导性质的文字来做开门钥匙是对论坛不利的。。。
回复 赞! 靠!

使用道具 举报

0

主题

1

回帖

16

积分

用户组: 初·技术宅

UID
184
精华
0
威望
1 点
宅币
12 个
贡献
1 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-4-8
发表于 2014-4-8 12:52:54 | 显示全部楼层
正好需要这个,谢谢
回复 赞! 靠!

使用道具 举报

0

主题

2

回帖

20

积分

用户组: 初·技术宅

UID
531
精华
0
威望
1 点
宅币
16 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-10-17
发表于 2014-10-17 09:31:46 | 显示全部楼层
这是我需要的,我可以下载吗?
回复 赞! 靠!

使用道具 举报

0

主题

3

回帖

28

积分

用户组: 初·技术宅

UID
545
精华
0
威望
2 点
宅币
21 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-11-10
发表于 2014-11-10 15:50:40 | 显示全部楼层
可以试试这个。
回复 赞! 靠!

使用道具 举报

0

主题

2

回帖

20

积分

用户组: 初·技术宅

UID
531
精华
0
威望
1 点
宅币
16 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-10-17
发表于 2014-11-11 16:36:11 | 显示全部楼层
szCompStr[uLen]=0;//结尾的\0

这一句是有问题的,只是在本程序中碰巧可以运行。但很感谢楼主的分享。希望认识楼主。看到的话请加我扣:289七叁四32。再次感谢楼主。
回复 赞! 靠!

使用道具 举报

1110

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24225 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
 楼主| 发表于 2014-11-11 17:33:20 | 显示全部楼层
dakuiz@163.com 发表于 2014-11-11 16:36
szCompStr=0;//结尾的\0

这一句是有问题的,只是在本程序中碰巧可以运行。但很感谢楼主的分享。希望认识楼 ...

szCompStr[uLen]=0;//结尾的\0

这一句是没有问题的。因为
szCompStr=(TCHAR*)malloc(uMem=(uLen+sizeof(TCHAR)));//分配内存
这句多分配了一个字符。所以我觉得没有问题。如果你觉得不是这个原因请告知我。
回复 赞! 靠!

使用道具 举报

1

主题

2

回帖

15

积分

用户组: 初·技术宅

UID
562
精华
0
威望
1 点
宅币
10 个
贡献
0 次
宅之契约
0 份
在线时间
2 小时
注册时间
2014-11-17
发表于 2014-11-19 16:41:05 | 显示全部楼层
有点意思。响应也挺快的。
回复 赞! 靠!

使用道具 举报

0

主题

2

回帖

19

积分

用户组: 初·技术宅

UID
611
精华
0
威望
1 点
宅币
15 个
贡献
0 次
宅之契约
0 份
在线时间
2 小时
注册时间
2014-12-23
发表于 2014-12-23 21:43:58 | 显示全部楼层
赞啊,太强大了
回复 赞! 靠!

使用道具 举报

0

主题

2

回帖

19

积分

用户组: 初·技术宅

UID
611
精华
0
威望
1 点
宅币
15 个
贡献
0 次
宅之契约
0 份
在线时间
2 小时
注册时间
2014-12-23
发表于 2015-1-9 14:30:35 | 显示全部楼层
楼主应该在写一篇如何获取TSF 框架输入法候选的文章~
回复 赞! 靠!

使用道具 举报

7

主题

4

回帖

5154

积分

用户组: 技术宅的结界VIP成员

UID
641
精华
1
威望
13 点
宅币
5111 个
贡献
1 次
宅之契约
0 份
在线时间
11 小时
注册时间
2015-1-28
发表于 2015-1-28 17:21:08 | 显示全部楼层
使用,全屏的时候需要
回复 赞! 靠!

使用道具 举报

1

主题

22

回帖

80

积分

用户组: 小·技术宅

UID
742
精华
0
威望
0 点
宅币
54 个
贡献
3 次
宅之契约
0 份
在线时间
6 小时
注册时间
2015-3-18
发表于 2015-3-18 21:56:20 | 显示全部楼层
谢谢楼主!我一直都在疑惑这个问题,终于知道资料了
回复 赞! 靠!

使用道具 举报

4

主题

41

回帖

160

积分

用户组: 小·技术宅

UID
208
精华
0
威望
1 点
宅币
113 个
贡献
0 次
宅之契约
0 份
在线时间
10 小时
注册时间
2014-4-16
发表于 2015-5-2 23:18:57 | 显示全部楼层
学长学长学长学长!!!我来啦
回复 赞! 靠!

使用道具 举报

0

主题

1

回帖

8

积分

用户组: 初·技术宅

UID
858
精华
0
威望
1 点
宅币
5 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2015-5-12
发表于 2015-5-12 13:18:19 | 显示全部楼层
看看看看看看看看
回复 赞! 靠!

使用道具 举报

蓝莓味绿茶 该用户已被删除
发表于 2015-7-22 15:34:37 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 赞! 靠!

使用道具 举报

0

主题

1

回帖

7

积分

用户组: 初·技术宅

UID
1032
精华
0
威望
1 点
宅币
4 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2015-8-10
发表于 2015-8-10 11:40:10 | 显示全部楼层
不错不错,要的就是这个效果
回复 赞! 靠!

使用道具 举报

卡卡 该用户已被删除
发表于 2015-8-10 16:49:04 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 赞! 靠!

使用道具 举报

0

主题

1

回帖

7

积分

用户组: 初·技术宅

UID
1067
精华
0
威望
1 点
宅币
4 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2015-8-23
发表于 2015-8-23 17:28:58 | 显示全部楼层
支持  不错 看看
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-19 17:11 , Processed in 0.056740 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表