一个MFC - Ansi工程,比较大,代码很多,加上也不是我写的,所以不要建议我把整个工程转为Unicode了,能走这条路我也不上来提问了。
它里面其中一个对话框,对话框上有个Edit , 是只读的,不用接受用户输入。
我想在这个Edit上显示Unicode字符串,不要叫我把Unicode转换成Ansi再显示,能这样做我也不会上来提问了。
关键是,有些Unicode字符,Ansi 根本显示不出来,出来的都是乱码或问号,比如Unicode编码0x2776,转到Ansi是0x3F,一个问号。
现在,就是想在这个CEdit上显示Unicode字符串,请教解决方案。
显式的使用Unicode API
Unicode字符串使用CStringW来保存
给Edit设置文本使用SetWindowTextW
CStringW str = L"你好";
m_edit.SetWindowTextW(str);
有这么简单就好了,你可以试试,如果是ansi的Edit, 你试试: m_edit.SetWindowTextW( (WCHAR*)"\x76\x27\x77\x27\x00\x00" );
相关函数会检查这个Edit使用的是ansi还是unicode, 如果是ansi,就会将unicode转换成ansi。 而以上字符串转换成ansi之后,将无法表示,是乱码。
每一个HWND,系统都会维护一个描述结构,这个结构中就标记了这个Wnd是ansi还是unicode, 是使用ansi还是unicode,只与这个标记有关,与你调用A版本还是U版本的函数一丁点关系也没有。
你翻看win2k的源代码就会看到,USER32!ValidateHwnd( HWND ) 将返回一个 PWND, PWND里有个PED, PED里有个32位的Flag,而第22位是:
UINT fAnsi : 1; /* is the edit control Ansi or unicode */
这个标记好像是无法在后期更改的,而是在CreateWindowEx时决定的,如果使用的是A版本,fAnsi 则会置1,如果使用的是W版本,则fAnsi置0。
当你对这个窗口进行字符串相关的操作的时候,无论你是使用A版本的函数还是W版本的函数,系统内部都会根据这个标记对字符串进行相关的转换!
当你以为使用CreateWindowExW进行创建Edit就可以解决这个问题的时候,想得太天真了。 确实,系统不再转换你提供的Unicode字符串,但是显示的时候,仍然是以Ansi代码页来显示,照样乱码!
我曾试过在ansi版本的Edit窗口创建之后, 手动将 UINT fAnsi 强制置0,然后直接调用 USER32!EditWndProcW , 发现Edit可以显示 ❶❷❸ 这类ansi显示不了的字符了,但是系统内部有地方处理缓冲区错误。
反了吧,一般都会创建UNICODE的工程,在需要的地方在使用ANSI