默认需要的是 UNICODE 字符集,简单的,我们把这个字符集改成 多字节字符集这个问题就解决了:
再试试应该就可以了吧?但是我并不推荐大家这么做,因为让自己 的
程序适应各种字符集是我们写代码的人义不容辞的义务。 我们把程序改成下面这样: #include
#include #include using namespace std; int main() { MessageBox( NULL, TEXT("你好 HelloWorld!"), TEXT("Information"), 0 ); MessageBox( NULL, _T("你好 HelloWorld!"), _T("Information"), 0 ); return 0; } 用两个宏 TEXT 或者_T 都可以解决这个问题,它们两个并没有太大区别, 也许区别在于前者是通过 windows.h 头文件引入的,而_T 是通过 tchar.h 引入 的,我推荐大家使用_T 和 tchar.h,因为 tchar.h 还帮助我们引入了其它一些很 有用的宏,比如_tcscpy_s,这个宏在使用 UNICODE 字符集的时候被替换成 wcscpy_s,在使用多字节字符集的使用被替换成 strcpy_s。关于这部分的内容, 请大家不要错过《Windows 核心编程》的第二章(第四版或第五版都可以), 核心编程》的第二章(第四版或第五版都可以), ),以 《 及《深入学习 C++ String2.1 版》。 它们都有提到。 《 有人听说_T 可以把多字节字符串转换成 UNICODE,因此他写了如下的代 码: const char* pStr = "haha 哈哈"; MessageBox( NULL, _T(pStr), _T("Information"), 0 ); 当然,除非你运气好的抓狂,否则你是编译不过去的,为什么呢?我们现 在应该知道对于"Hello"这样的字符串,VC2010 会默认的将它视为 const char*, 即多字节字符串,而 L"Hello"前面有个 L 前缀的被视为 UNICODE 字符串,这和 C#是有区别的,因为 C#的字符串总是被视为 UNICODE,C++/CLI 下面
编译器也会 帮助我们做到这件事情,所以它们不需要 L(C++/CLI 兼容 L 这种写法)。 让我们看看_T 的定义吧: #define wxCONCAT_HELPER(text, line) text ## line /* could already be defined by tchar.h (it's quasi standard) */ #ifndef _T
#if !wxUSE_UNICODE #define _T(x) x #else /* Unicode */ /* use wxCONCAT_HELPER so that x could be expanded if it's a macro */ #define _T(x) wxCONCAT_HELPER(L, x) #endif /* ASCII/Unicode */ #endif /* !defined(_T) */ _T 在 UNICODE 下面最终会被替换成 L ## x。 ##是一个编译预处理指令, 意味着让 L 和 x 贴在一起,比如 L ## "Hello"最终就是 L"Hello",因此它可以 把"Hello"转换成 UNICODE 字符串。那为什么上面的程序不行呢?让我们看看 _T("pStr")会被替换成什么:L ## pStr -> LpStr,哦,LpStr 是一个新的标识 符,如果你没有定义过它,你当然不能通过编译啦。 因此我们可以了解到_T 这样的宏只能处理直接的常量字符串,不能处理 其它的情况。而我们上面演示的那种情况需要我们动态的去转换编码,Windows 有 API 可以帮助我们做到,C 库也有函数可以帮助我们。恰好我曾经写过这样的 ASCII/UNICODE/UTF8 C++代码 代码,欢迎大家参考:ASCII/UNICODE/UTF8 字符串互相转换的 C++代码 对于_T 宏,再说一点东西,或许你会感到奇怪为什么_T 不直接定义成 #define _T(x) L ## x,而要绕个圈子去调用 wxCONCAT_HELPER 呢?这实际上涉 及到宏展开顺序和截断的问题。在这里,我们需要说一个宏参数的概念,这很函 数的参数是类似的,这里_T(x)的 x 就是宏参数,好,记住下面一句话: 如果你定义的宏中使用了#或者是##的话,宏参数将不会被展开,也就是说 _T(x)如果直接定义成 L##x 那么在下面这种情况就会出错( PS: #是给参数加引 号的意思): _T(__FUNCTION__),__FUNCTION__是一个预定义的宏,它代表了当前函数 的名字,这个展开会是什么呢?L__FUNCTION__。为什么间接调用 wxCONCAT_HELPER 就能得到正确的结果呢?因为当我们调用 wxCONCAT_HELPER 的 时候,__FUNCTION__已经被_T 展开成了函数名。 说