WM_CHAR WM_IME_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)定义全局数组 ,存放键盘输入的字符

<code>	

wchar_t

m_ImeChar[

2

];/<code>
WM_CHAR   WM_IME_CHAR 有什么区别

常用字的unicode占用2个字节

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

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

2)重载窗口处理过程

<code>	

virtual

LRESULT

WindowProc

(UINT message, WPARAM wParam, LPARAM lParam)

;/<code>
WM_CHAR   WM_IME_CHAR 有什么区别


<code>WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_IME_CHAR:
		 
		

if

(PreTreat(WM_IME_CHAR,wParam,lParam))

break

;

if

(m_ImeChar[

0

]>=

0xD800

&& m_ImeChar[

0

]<=

0xDBFF

) { m_ImeChar[

1

]=(wchar_t)wParam; }

else

{ m_ImeChar[

0

]=(wchar_t)wParam;

if

(m_ImeChar[

0

]>=

0xD800

&& m_ImeChar[

0

]<=

0xDBFF

)

break

; } OnImeChar(m_ImeChar);

break

;

default

:

break

; }

return

CScrollView::WindowProc(message, wParam, lParam); }/<code>
WM_CHAR   WM_IME_CHAR 有什么区别


说明:

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

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

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


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

BMP内,从U+D800到U+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)对数组中接受的字 进行处理


<code>	

void

OnImeChar

(

wchar_t

* Str)

;/<code>
WM_CHAR   WM_IME_CHAR 有什么区别


<code>OnImeChar(

wchar_t

* Str) { 。。。 } /<code>
WM_CHAR   WM_IME_CHAR 有什么区别

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

<code>OnChar(

UINT

nChar,

UINT

nRepCnt,

UINT

nFlags) {

switch

(nChar) {

case

0x0D

:

if

(PreTreat(

0x0D

,

NULL

,

NULL

))

break

; OnEnterKeyDown(); Update();

break

;

case

0x08

:

if

(PreTreat(

0x08

,

NULL

,

NULL

))

break

;

if

(m_paSelElem.GetSize()>

0

) OnDelElemsel();

else

OnBackSpaceKeyDown(); Update();

break

;

case

0x20

:

if

(PreTreat(

0x20

,

NULL

,

NULL

))

break

; OnSpaceKeyDown(); Update();

break

;

case

0x09

:

if

(PreTreat(

0x09

,

NULL

,

NULL

))

break

; OnTabKeyDown(); Update();

break

;

default

:

break

; }

if

(m_paSelElem.GetSize()>

0

) { CleanSelElem(); } CScrollView::OnChar(nChar, nRepCnt, nFlags); } /<code>
WM_CHAR   WM_IME_CHAR 有什么区别


处理原则:

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

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



分享到:


相關文章: