1,在VS2010 编译器的菜单上 “项目----属性---左侧的配置属性----常规---右侧的 字符集 ”可以对项目所要使用的字符集进行定义,可以选择”使用Unicode字符集“、“使用多字节字符集”等等。
2,MessageBox 有三个版本:MessageBoxA, MessageBoxW, MessageBox;
****************************************
WINUSERAPI
int
WINAPI
MessageBoxA(
WINUSERAPI
int
WINAPI
MessageBoxW(
#ifdef UNICODE
#define MessageBox
#else
#define MessageBox
#endif // !UNICODE
**********************************************
即:如果项目设置使用UNICODE字符集, MessageBox 就是 MessageBoxW, 否则 MessageBox就是 MessageBoxA;
在MessageBoxA函数的第二和第三个参数的类型都是LPCSTR ,它是什么呢?
typedef __nullterminated CONST CHAR *LPCSTR, *PCSTR;
它是 CONST CHAR, CONST CHAR 是什么?
#ifndef CONST
#defineCONST
#endif
typedef char CHAR;
所以 CONST CHAR 就是 const char; 所以MessageBoxA中的第二和第三个参数要是多字节(ANSI)类型常量的。
在MessageBoxW函数的第二和第三个参数的类型都是LPCWSTR ,它是什么呢?
typedef __nullterminated CONST WCHAR *LPCWSTR, *PCWSTR;
它是 CONST WCHAR; CONST WCHAR又是什么?
#ifndef CONST
#defineCONST
#endif
#ifndef _MAC
typedef wchar_tWCHAR;
#else
// some Macintosh compilers don't define wchar_t in a convenientlocation, or define it as a char
typedef unsigned shortWCHAR;
#endif
所以CONST WCHAR 就是 const wchar_t ,所以MessageBoxW中的第二和第三个参数要是16位的UNICODE 常量。
3,CString 也有三个版本,CStringA, CStringW, CString;
**************************************************
typedef ATL::CStringT< wchar_t,StrTraitMFC_DLL< wchar_t >> CStringW;
typedef ATL::CStringT< char,StrTraitMFC_DLL< char >> CStringA;
typedef ATL::CStringT< TCHAR,StrTraitMFC_DLL< TCHAR >> CString;
******************************************************************
4,上面CString 模板中的 TCHAR 是什么?
*****************************************************************
//
// Neutral ANSI/UNICODE types and macros
//
#ifdef
#ifndef _TCHAR_DEFINED
typedef WCHAR TCHAR, *PTCHAR;
typedef WCHAR TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif
#else
#ifndef _TCHAR_DEFINED
typedef char TCHAR, *PTCHAR;
typedef unsigned char TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif
即:如果项目设置使用UNICODE字符集 ,TCHAR 就是 WCHAR,也就是wchar_t;否则 TCHAR 就是char;所以项目设置使用UNICODE字符集, CString就是CStringW, 否则CString 就是CStringA.
5 在给宽字节变量赋值时,可以在值前加“L”,也可以加“_T”,比如:
#define_T(x)
#define_TEXT(x)
那么 __T(x) 是什么?
#ifdef
#define __TEXT(quote)L##quote
#else
#define __TEXT(quote)quote
#endif
即:如果项目设置使用UNICODE字符集, “_T” 就相当于“L”,否则加“_T”就如同没加。
6
比如一条语句:
CString
在项目设置使用UNICODE字符集时,CString 就相当于 CStringW, x中存储的字符长度为3,_T就相当于L;在项目设置使用多字节字符集时,CString 就相当于CStringA, x中存储的字符长度为6。
而string 和 wstring 却没有类似的转化功能。
typedef basic_string<char,char_traits<char>,allocator<char> >string;
typedef basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >wstring
当然如果处于某种考虑,某个变量就要存储 宽字节字符,而不是存储ANSI字符,就可以显式的使用CStringW类型,而不是使用CString。
补充说明:编译错误。
_T只能把字符串文字量(也就是双引号括起来的字符串)或者字符文字量(也就是单引号括起来的字符)转化为所需的样子。它无法把一个CHAR转化为一个TCHAR,也无法把一个LPSTR转化为一个LPTSTR。
为什么会这样呢?答案是:因为C++语法。
目前的C++语法,支持两种字符串。一种是直接用引号括起的,比如"Hello, World.",另一种是用引号括起,前面再加一个字母L的,比如L"Hello, World."。前一种字符串的类型是char*,或者说是const char*,后一种字符串的类型是wchar_t*,或者说是const wchar_t*。
在Visual Studio 2010中,_T是一个宏。它的作用是:如果当前的工程设置是Unicode,则在前面加一个L,否则就什么也不加。换句话说,如果工程设置为Unicode,_T("a")就相当于L"a",否则,_T("a")就相当于"a"。楼主写一个_T(text),如果工程设置为Unicode,就变成了Ltext,于是编译就出错了:没有Ltext这个变量。
如何解决?
方法1、如果是从Visual Studio 6.0升级过来的代码,因为它的工程默认设置不是Unicode的,而Visual Studio 2010的工程默认设置是Unicode的,造成问题。遇到这种情况,直接在Visual Studio 2010里面修改工程设置为不是Unicode即可。
方法2、对于那个函数而言,可以调用TextOut的非Unicode版本。
TextOut(xdc,x,y,_T(text),strlen(text));
修改为
TextOutA(xdc,x,y,text,strlen(text));
方法3、如果彻底一点,一定要用Unicode的话,微软提供了MultiByteToWideChar函数,可以用于转化,楼主可以查查这方面的资料。