Windows 开发中的字符串
- W_Z_C
- 共 966 字,阅读约 2 分钟
Windows 操作系统天然支持 Unicode 字符串。这些字符串经常被用在 UI 组件、文件名等字符相关的地方。因为 Windows 操作系统会涉及到多语言的问题,所以 Unicode 是首选的字符串编码方式。
和 Linux 使用 UTF-8 编码不同,Windows 平台使用 UTF-16 编码方式,每个字符用16位的值表示。UTF-16 字符也被叫做宽字符。Visual Studio C++ 编译器支持内置的宽字符类型 wchar_t ,具体定义在头文件 WinNT.h
中。
typedef wchar_t WCHAR
声明一个宽字符或者一个宽字符串需要将 L 放到文件前面:
wchar_t a = L'a';
wchar_t *str = L"hello";
项目有一些常见的字符串类型:
类型 | 定义 |
---|---|
CHAR | char |
PSTR or LPSTR | char* |
PCSTR or LPCSTR | const char* |
PWSTR or LPWSTR | wchar_t* |
PCWSTR or LPCWSTR | const wchar_t* |
1. Unicode 和 ANSI 函数
因为微软提供对 Unicde 的支持,所以它将每个和字符串相关的 API 都提供了两个版本,一种是 ANSI 字符串版本,另一种是 Unicode 字符串版本。例如,下面两个 API 都是设置窗口标题的接口:
- SetWindowTextA 需要传入 ANSI 字符串。
- SetWindowTextW 需要传入 Unicode 字符串。
在函数内部,ANSI 版本的接口会将 ANSI 字符串转换为Unicode 字符串,然后再调用 Unicode 版本接口完成操作。
为了方便微软在头文件中还定义了一个 UNICODE 宏来区分不同版本的调用。
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif
使用上面的方法可以避免在代码中区分具体调用的接口是 UNICODE 版本还是 ANSI 版本。相反的,在程序中只需要直接调用 SetWindowText 函数设置标题即可。编译的时候会自动根据 UNICODE 宏定义来决定使用哪个版本。
除非兼容旧的程序或者组件,否则在开发新应用的时候,应该一直使用 Unicode 版本。因为 Windows 操作系统支持多语言,如果使用 ANSI 版本,它将无法支持应用程序的本地化,并且 ANSI 版本的接口效率更低,因为其内部需要进行编码转换。
2. TCHARs
如果你的程序需要同时支持多款操作系统,如:Windows NT、Windows 95、Windows 98 和 Windows Me。这时候你需要明确区分使用的是 ANSI 版本还是 Unicode 版本字符串,为了进一步方面开发,Windows 提供一个宏来完成二者的自动区分。
宏 | Unicode | ANSI |
---|---|---|
TCHAR | wchar_t | char |
TEXT(“x”) | L”x” | “x” |
举个例子:
SetWindowText(TEXT("My Application"));
该语句等价于:
SetWindowTextW(L"My Application"); // Unicode function with wide-character string.
SetWindowTextA("My Application"); // ANSI function.
如今,TEXT 和 TCHAR 宏的用处已经很小了,因为所有的程序都应该使用 Unicode 字符,然而你在一些老的程序中仍然看见它们的身影。
除了上边的问题,在头文件中,微软 C 运行时库中,仍然存在类似的宏定义,例如涉及到字符操作的函数:
#ifdef _UNICODE
#define _tcslen wcslen
#else
#define _tcslen strlen
#endif
一些头文件使用 UNICODE 宏,另一些使用 _UNICODE 宏,最好同时定义它们,如果你是用 Visual C++ 创建工程,这些会默认自动进行设置。