WM_IME_CHAR 与WM_CHAR的区别

要理解二者的区别,首先需要清楚:   我们通过键盘所打的字,并不都是全部通过输入法后,转交给程序的。

      也就是说: 我们用键盘打的字有些是不经过输入法直接传送到程序中,如1、2、3这样的数字 还有ABC英文字母,回车 空格等

                             有些是经过输入法转交给程序的,如中文

      明白这点后,WM_IME_CHAR与WM_CHAR的区别就容易理解了。

      需要说明的是: 数字和英文字母 你可以不通过输入法直接输入,也可以通过输入法进行输入

     

       WM_IME_CHAR: 所有经由输入法产生的字符都会产生WM_IME_CHAR消息。

                                          DefWindowProc会将WM_IME_CHAR转换为WM_CHAR消息

 

       WM_CHAR:            未经输入法而直接送人程序中的字符会响应WM_CHAR消息。

 

说明:

对于 Unicode 窗口,WM_IME_CHAR 和 WM_CHAR 没有区别,wParam 都是一个 WCHAR,即输入的字符。

对于非 Unicode (DBCS) 窗口,WM_IME_CHAR 的 wParam 即由输入法生成的一个字符。这个字符既有可能是单字节字符也有可能是双字节字符。如果是单字节字符,那么和 WM_CHAR 没什么区别;如果是一个双字节字符,那么 wParam 高 8 位为 Leading byte,低 8 位为 Continuation Byte。

所有经由输入法产生的字符都会产生 WM_IME_CHAR 消息而不是 WM_CHAR,但 DefWindowProc会把 WM_IME_CHAR 转换为相应的一个或两个 WM_CHAR 消息。

例如:

  • 不开输入法输入「9」 → 收到 WM_CHAR (0×0039)
  • 打开输入法输入「9」 → 收到 WM_IME_CHAR (0×0039) → 收到 WM_CHAR (0×0039)
  • 打开输入法输入「笨」 → 收到 WM_IME_CHAR (0xB1BF) → 收到 WM_CHAR (0x00B1) → 收到 WM_CHAR (0x00BF)

 

 

 

 

编程实现:

 

      对于WM_CHAR   MFC提供了其响应函数OnChar(),  但对于WM_IME_CHAR 并没有提供其响应函数,需要我们自己去写

     下例程序显示了如何处理键盘字符消息的过程:

 

1)定义全局数组 ,存放键盘输入的字符

[cpp]  view plain  copy
  1. wchar_t m_ImeChar[2];  

       常用字的unicode占用2个字节

        而冷僻字的unicode需要占用4个字节

       因此,  定义4自己的数组 存放字


2)重载窗口处理过程

[cpp]  view plain  copy
  1. virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);  

 

[cpp]  view plain  copy
  1. WindowProc(UINT message, WPARAM wParam, LPARAM lParam)  
  2. {  
  3.     switch(message)  
  4.     {  
  5.     case WM_IME_CHAR:  
  6.         //对特殊字符 进行预处理  
  7.         if(PreTreat(WM_IME_CHAR,wParam,lParam)) break;  
  8.   
  9.         //其他字符 放入数组中  
  10.         if(m_ImeChar[0]>=0xD800 && m_ImeChar[0]<=0xDBFF)  
  11.         {  
  12.             m_ImeChar[1]=(wchar_t)wParam;  
  13.         }  
  14.         else  
  15.         {  
  16.             m_ImeChar[0]=(wchar_t)wParam;  
  17.             if(m_ImeChar[0]>=0xD800 && m_ImeChar[0]<=0xDBFF)  
  18.                 break;  
  19.         }     
  20.         OnImeChar(m_ImeChar);  
  21.         break;  
  22.     default:   
  23.         break;  
  24.     }  
  25.     return CScrollView::WindowProc(message, wParam, lParam);  
  26. }  


 

说明:

      unicode编码       U+0000 ~ U+FFFF                为基本多语言平面(Basic MultilingualPlane,简记为BMP

                                    U+10000 ~ U+10FFFF        为16个辅助平面

     常用字都处在BMP内,占2个字节;而冷僻字则在BMP之外,占四个字节。

 

     常用字、冷僻字区别方法: 

                                                      BMP内,从U+D800U+DFFF之间的Code Point区段是永久保留不映射到字符

                                                      BMP之外占用四个字节 前两个字节为高位字节,后两个字节为低位字节

                                                     前两个字节的范围为:0xD800..0xDBFF

                                                     后两个字节的范围为:0xDC00..0xDFFF

       由此可见,BMP之内的字符 和BMP之外的字符没有交集。

       因此,

          if(m_ImeChar[0]>=0xD800 && m_ImeChar[0]<=0xDBFF)

              如果满足这个条件,则表示的是占用4个字节的冷僻字

       对于冷僻字,系统会发送两次WM_IME_CHAR消息,第一次传送其高位字节,第二次传送其低位字节

 

       当运行到OnImeChar(m_ImeChar);时, m_ImeChar存放的为真实的字(不管是常用字还是冷僻字,此时都正确保存在了此数组中)

 

      

3)对数组中接受的字 进行处理

 

[cpp]  view plain  copy
  1. void OnImeChar(wchar_t* Str);  

 

[cpp]  view plain  copy
  1. OnImeChar(wchar_t* Str)  
  2. {  
  3.     。。。  
  4. }         


4)使用OnChar响应未经输入法输入的字符

[cpp]  view plain  copy
  1. OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
  2. {  
  3.     switch(nChar)  
  4.     {  
  5.     case 0x0D:                                                  //回车键  
  6.         if(PreTreat(0x0D,NULL,NULL)) break;  
  7.   
  8.         OnEnterKeyDown();  
  9.         Update();  
  10.         break;  
  11.     case 0x08:                                                  //退格键  
  12.         if(PreTreat(0x08,NULL,NULL)) break;  
  13.   
  14.         if(m_paSelElem.GetSize()>0) OnDelElemsel();  
  15.         else OnBackSpaceKeyDown();  
  16.         Update();  
  17.         break;  
  18.     case 0x20:                                                  //空格键  
  19.         if(PreTreat(0x20,NULL,NULL)) break;  
  20.   
  21.         OnSpaceKeyDown();  
  22.         Update();  
  23.         break;    
  24.     case 0x09:                                                  //TAB键  
  25.         if(PreTreat(0x09,NULL,NULL)) break;  
  26.   
  27.         OnTabKeyDown();  
  28.         Update();  
  29.         break;  
  30.     default:  
  31.         break;  
  32.     }  
  33.   
  34.     if(m_paSelElem.GetSize()>0)  
  35.     {  
  36.         CleanSelElem();  
  37.     }  
  38.   
  39.     CScrollView::OnChar(nChar, nRepCnt, nFlags);  
  40. }  

 


 

处理原则:

                 对于WM_IME_CHAR消息,则交由WM_IME_CHAR响应函数处理

                 对于不经输入法的字符消息,则交由WM_CHAR进行处理

 

 

 

     

 参考资料:

http://timothyqiu.com/2012/wm_ime_char/

 

 

 

 

 

 

 

                          

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值