使用消息钩子实现CEGUI中文输入

CEGUI是OGRE默认推荐的一个界面库.虽然Ogre官方表示CEGUI不是唯一的选择,但是我想很多人会因为Ogre的关系而选择CEGUI库.但是CEGUI内部使用的是UNICODE,使得在支持中文上有一些问题.

      目前网上解决方案大多是不使用Ogre的默认的窗口,而是自己使用windows API创建自己的窗口,处理WM_CHAR消息,实现中文输入.但我觉得这个方案似乎动作太大了点.自己管理窗口意味着自己还要处理一些诸如窗口移动等许多消息.我个人觉得麻烦.一个程序员,要节省自己的时间,唯一的办法就是不要自己发明轮子.

  我花了大概一天的时间在网上查找资料.整个中文输入的流程大概是这样:当客户输入中文的时候,windows系统的ime库拦截到响应的输入信息,做出一系列处理后,将输入转换成中文,把结果用WM_CHAR消息发送给应用程序,然后应用程序处理WM_CHAR消息,在相应的输入窗口显示中文.整个流程看起来是这样:

    输入的按键消息 -> IME转换为中文 -> IME发送WM_CHAR消息 -> 应用程序窗口响应并显示消息

  Ogre之所以存在中文输入的问题在于Ogre的默认窗口是不能处理WM_CHAR消息的.据我所知国内解决这个问题除了上面说的办法外,还有个办法是修改Ogre的源代码.但是同样的,这个手术太大了.既然问题在于应用程序的窗口不能响应消息,那我们就想个办法自己处理WM_CHAR消息好了.毕竟IME的工作是很正常的,即便我们使用的是Ogre默认窗口,WM_CHAR仍然在发送.

  使用消息钩子HOOK可以做到这一点.因为整个程序的源代码都是我自己写,所以我可以使用一个局部钩子,直接添加个函数进源代码.这个函数看上去是这样:

 

[c-sharp]  view plain copy
  1. //局部钩子函数 截取WM_CHAR消息实现中文输入  
  2. LRESULT CALLBACK ChineseCharHookProc(int nCode, WPARAM wParam, LPARAM lParam)  
  3. {  
  4.     if(nCode < 0)  
  5.         return CallNextHookEx(g_hHook,nCode,wParam,lParam);  
  6.   
  7.     if(!ImmIsIME(GetKeyboardLayout(0)))  
  8.         return CallNextHookEx(g_hHook,nCode,wParam,lParam);  
  9.   
  10.     MSG* msg = (MSG*)lParam;  
  11.     switch(msg->message)  
  12.     {  
  13.     case WM_CHAR:  
  14.         {  
  15.             switch(msg->wParam)  
  16.             {  
  17.                 //输入状态下的特殊功能键位处理  
  18.             case VK_RETURN:  
  19.                 {  
  20.                     CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Return);  
  21.                     break;  
  22.                 }  
  23.   
  24.             case VK_TAB:  
  25.                 {  
  26.                     CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Tab);  
  27.                     break;  
  28.                 }  
  29.   
  30.             case VK_BACK:  
  31.                 {  
  32.                     CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Backspace);  
  33.                     break;  
  34.                 }  
  35.   
  36.             default:  
  37.                 {  
  38.                     CEGUI::utf32 utf = (CEGUI::utf32)(msg->wParam);  
  39.                     CEGUI::System::getSingleton().injectChar(utf);  
  40. //                  CEGUI::Window* w = CEGUI::WindowManager::getSingleton().getWindow("Root/Input");  
  41. //                  w->setText(w->getText() + utf);  
  42.                     return true;  
  43.                 }  
  44.                 break;  
  45.             }  
  46.         }  
  47.     }  
  48.   
  49.     return CallNextHookEx(g_hHook,nCode,wParam,lParam);  
  50. }  

 

ImmIsIME(GetKeyboardLayout(0))这个函数检查输入法状态是否打开.所以这个函数的作用就是检查输入法,当打开输入法的时候把输入转换成CEGUI可以识别的模式.

另外在构造和析构函数要分别添加:

g_hHook =SetWindowsHookEx(WH_GETMESSAGE,ChineseCharHookProc,NULL,GetCurrentThreadId())

UnhookWindowsHookEx(g_hHook)

语句.OIS的capture代码段要加入对输入法状态的判断,否则会造成双重输入.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值