WEB开发网
开发学院软件开发C++ C++字符串完全指引之一:Win32 字符编码 阅读

C++字符串完全指引之一:Win32 字符编码

 2010-10-15 09:08:06 来源:Web开发网   
核心提示:Win32 API中的MBCS和Unicode两组 APIs:尽管你也许从来没有注意过,Win32中的每个与字符串相关的API和message都有两个版本,C++字符串完全指引之一:Win32 字符编码(4),一个版本接受MBCS字符串,另一个接受Unicode字符串,其他的函数如, _stprintf(代替sprin

Win32 API中的MBCS和Unicode

两组 APIs:

尽管你也许从来没有注意过,Win32中的每个与字符串相关的API和message都有两个版本。一个版本接受MBCS字符串,另一个接受Unicode字符串。例如,根本没有SetWindowText()这个API,相反,有SetWindowTextA()和SetWindowTextW()。后缀A表明这是MBCS函数,后缀W表示这是Unicode版本的函数。

当你 build 一个 Windows 程序,你可以选择是用 MBCS 或者 Unicode APIs。如果,你曾经用过VC向导并且没有改过预处理的设置,那表明你用的是MBCS版本。那么,既然没有 SetWindowText() API,我们为什么可以使用它呢?winuser.h头文件包含了一些宏,例如:

BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif

当使用MBCS APIs来build程序时,UNICODE没有被定义,所以预处理器看到:

#define SetWindowText SetWindowTextA

这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。(当然,你可以直接调用SetWindowTextA() 或者 SetWindowTextW(),虽然你不必那么做。)

所以,如果你想把默认使用的API函数变成Unicode版的,你可以在预处理器设置中,把_MBCS从预定义的宏列表中删除,然后添加UNICODE和_UNICODE。(你需要两个都定义,因为不同的头文件可能使用不同的宏。) 然而,如果你用char来定义你的字符串,你将会陷入一个尴尬的境地。考虑下面的代码:

HWND hwnd = GetSomeWindowHandle();
char szNewText[] = "we love Bob!";
SetWindowText ( hwnd, szNewText );

在预处理器把SetWindowText用SetWindowTextW来替换后,代码变成:

HWND hwnd = GetSomeWindowHandle();
char szNewText[] = "we love Bob!";
SetWindowTextW ( hwnd, szNewText );

看到问题了吗?我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义:

HWND hwnd = GetSomeWindowHandle();
#ifdef UNICODE
wchar_t szNewText[] = L"we love Bob!";
#else
char szNewText[] = "we love Bob!";
#endif
SetWindowText ( hwnd, szNewText );

你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR.

使用TCHAR

TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用同样的代码,不需要使用繁琐的宏定义来包含你的代码。TCHAR的定义如下:

#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif

所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。

#ifdef UNICODE
#define _T(x) L##x
#else
#define _T(x) x
#endif

##是一个预处理操作符,它可以把两个参数连在一起。如果你的代码中需要字符串常量,在它前面加上_T宏。如果你使用Unicode来build,它会在字符串常量前加上L前缀。

TCHAR szNewText[] = _T("we love Bob!");

像是用宏来隐藏SetWindowTextA/W的细节一样,还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如,你可以使用_tcsrchr宏来替换strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数,就像SetWindowText所作的一样。

不仅str***()函数有TCHAR宏。其他的函数如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."标题下有完整的宏列表。

上一页  1 2 3 4 5  下一页

Tags:字符串 完全 指引

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接