北大中文论坛 www.pkucn.com

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
楼主: 路路通

输入法编程漫谈(08-09-07更新)

[复制链接]
发表于 2008-6-12 16:01:43 | 显示全部楼层
原来你的文件是exe,不是dll。

[ 本帖最后由 三三龙 于 2008-6-12 16:53 编辑 ]
发表于 2008-6-13 20:59:54 | 显示全部楼层
煩請胡樓主、胡老師來教教大家關於輸入法於Vista的作業系統中的接口方面的知識?可以嗎?先謝謝樓主。
 楼主| 发表于 2008-6-14 15:21:10 | 显示全部楼层

键盘消息的处理

我们通过窗口子类化的手段将操作系统发给对话框的键盘消息截取后,接下来就是如何处理这些消息了。
        键盘的消息很多,我们只需要处理对我们有用的消息。
        输入法需用到的虚拟键主要有两类:用于编码的键和功能键。编码键一般就是26个字母键、数字键、标点符号键,可根据自己的输入法进行增减;功能键就是空格键、退格键、Esc键、4个方向键、用于翻页的键等。下面以拼音输入法为例子来说说按键消息的处理:
        
         case WM_CHAR:
                  flg = CharHandler(hWnd,wParam,lParam);
                         break;
          case WM_KEYDOWN:
                  flg = FunKeyHandlerNormal(hWnd,wParam,lParam);
                          break;
  
         VK_ESCAPE键是取消编码串,由于编码串变量g_PYBMStr是全局变量,因此要调用函数InitPYBMStr()将其清空。
         VK_DELETE、VK_BACK与编码键都是对字符串的操作,C语言的教科书上都有例子,不难理解。
         VK_SPACE与10个数字键是对候选框的词条进行选择。这个比较关键,你的短语取代操作系统默认的字符就是在这里处理。

         VK_HOME、VK_END、VK_LEFT、VK_UP、VK_RIGHT、VK_DOWN是对编码串上面光标(插入符)移动的操作,在设计你的编码串结构的时候,必须要有一个变量存储插入符的位置。

         a~z键用于编码输入。

         “=”、 “.”用于向前翻页,“-”、“,”用于向后翻页。

         功能键必须是在编码串的长度不为零的情况下才需要处理,这个初学者要注意。还有光标(插入符)的操作记得通知操作系统刷新一下对应的窗体,否则插入符会呆在原地不动。
 楼主| 发表于 2008-6-21 20:56:02 | 显示全部楼层

将字串发送到宿主程序

将选好的字串发送到宿主程序是输入法程序的目的,这个过程就是程序的核心,其它的工作都是围绕这个核心而展开的。初学者首先要认清这个事实,不要把输入法编程想象的很复杂,学任何东西都一样,一定要把握它住的本质,然后逐层展开,最后搞清楚它的方方面面,这样才能学到它的精髓,这样才能事半功倍。
        
        我们先来看看示范程序是如何把字串发送到EDIT控件的:
        
case MY_WM_IME_COMPOSITION:
          //获得最终候选串的指针
          lpszResult = GetCompResultStr();
          if (lpszResult)
          {
                   while(*(lpszResult) != _T('\0'))
                  {
                          //用特快专递将字串发送到EDIT控件
                         SendMessage(hWndEdit,WM_CHAR,(WPARAM)(*lpszResult),0);
                         lpszResult++;
                  }
           }
          //字串发送完毕,隐藏候选窗体
           MoveCandWindow();
  
          //对组合串结构和候选串结构初始化
          InitPYBMStr();
          InitCandStrPage();
  
          break;
        
          再来看看标准的输入法程序是如何做的:
BOOL MakeResultString(BOOL fFlag)
{
         HIMC   hIMC  = NULL;
         LPINPUTCONTEXT  lpIMC  = NULL;
         LPCOMPOSITIONSTRING lpIMECompStr = NULL;
         LPTSTR   lpConvStr = NULL;
         GENEMSG   GnMsg  = {0};

         hIMC = (HIMC)GetWindowLong(GetUIWnd(), IMMGWL_IMC);
         if (!hIMC)
        {
                 MessageBeep((UINT)-1);
                 return FALSE;
        }

        if (!(lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC)))
        {
                MessageBeep((UINT)-1);
                return FALSE;
         }
         lpIMC = ImmLockIMC(hIMC);
         lpIMECompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
         if (fFlag)
         {
                 lpConvStr = GetConvStr();
                 if (!lpConvStr) return FALSE;
                _tcscpy((LPTSTR)((LPBYTE)(lpIMECompStr) + (lpIMECompStr)->dwResultStrOffset),lpConvStr);
               lpIMECompStr->dwResultStrLen = _tcslen(lpConvStr);
          }
         else
         {
                *((LPTSTR)((LPBYTE)(lpIMECompStr) + (lpIMECompStr)->dwResultStrOffset)) = _T('\0');
                lpIMECompStr->dwResultStrLen = 0;
         }

         InitCompADT();
         ImmUnlockIMCC(lpIMC->hCompStr);

        GenerateMessage(WM_IME_COMPOSITION,0,GCS_RESULTSTR);
        GenerateMessage(WM_IME_ENDCOMPOSITION,0,0);
        ImmUnlockIMC(hIMC);
        return TRUE;
}   

         一直到if (fFlag)这行代码为止,之前的那些都是为了取得IMC结构中存放结果串的内存块,没有别 的目的。你选好的字串必须先放到这里,然后才能帮你发送出去。你可能要问为什么不能直接发送呢? 先来看看我们现在是怎么杀猪。农民兄弟把猪养大了,一刀把它杀了拿去 卖钱行吗?不行,政府有规定生猪要定点屠宰,理由是:一、可以防止病猪、老母猪、灌水猪上市, 二、各种收费有绝对的保障,你明白其中的道理了吧?

[ 本帖最后由 路路通 于 2008-6-22 12:42 编辑 ]
发表于 2008-6-21 22:40:02 | 显示全部楼层

输入法用哪种程序编程比较好?

C、C++、B(basic)、J(java)?

[ 本帖最后由 求实—求知 于 2008-6-22 15:15 编辑 ]
发表于 2008-6-22 22:59:49 | 显示全部楼层
ImmLockIMC(hIMC);

我就是看 不懂这个东西到底干什么用,还跟另一个函数来配用。
 楼主| 发表于 2008-6-23 07:57:07 | 显示全部楼层

回复 36楼 的帖子

发表于 2008-7-1 22:41:19 | 显示全部楼层
原帖由 路路通 于 2008-6-12 07:50 发表
收徒弟,恐不够资格,交个朋友吧。
        你的詹码做得那么好,还要学习?是逗我玩吧,或者想收我做徒弟?


我想用VC编输入法软件,不是开玩笑。
这方面的资料手头没有,希望您得到你的指点。
 楼主| 发表于 2008-7-2 06:59:51 | 显示全部楼层
原帖由 zhlzh 于 2008-7-1 22:41 发表
我想用VC编输入法软件,不是开玩笑。
这方面的资料手头没有,希望您得到你的指点。


有一事不明,你的手机输入法和PC输入法是怎么做出来的?

[ 本帖最后由 路路通 于 2008-7-2 07:00 编辑 ]
发表于 2008-7-2 10:50:42 | 显示全部楼层
手机输入法是我自己做的,是网络语言。
PC输入法是教授给做的,是VC++语言。
 楼主| 发表于 2008-7-2 10:53:28 | 显示全部楼层
原帖由 zhlzh 于 2008-7-2 10:50 发表
手机输入法是我自己做的,是网络语言。
PC输入法是教授给做的,是VC++语言。

呵,原来是这样。
教授没给你源代码吗?是看不懂源代码呢,还是别的什么原因?
发表于 2008-7-2 10:56:58 | 显示全部楼层
有源代码看不懂。
 楼主| 发表于 2008-7-2 10:58:56 | 显示全部楼层
如果你有VC的基础,输入法编程还是挺简单的(指公用部分,不算码表处理部分),等有时间我把标准的输入法程序放上来你就会知道我所言不虚。
 楼主| 发表于 2008-7-2 11:05:26 | 显示全部楼层
原帖由 zhlzh 于 2008-7-2 10:56 发表
有源代码看不懂。

绝大多数的输入法程序都用了Microsoft默认的非常复杂的数据结构,有的还把自己的结构加一块进去,所以很多初学者都是晕头转向,耐心等着吧,我把标准的输入程序放上来,应该对你有所帮助。
发表于 2008-7-2 11:10:12 | 显示全部楼层
谢谢您,您不愧是大师。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大中文系 ( 京ICP备12040209号

GMT+8, 2016-3-24 20:39 , Processed in 0.126518 second(s), 19 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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