如果調用任何windows函數,并傳遞給他一個ANSI字符串,系統會先將這個字符串轉換為unicode字符串,然后將這個unicode字符串傳遞給操作系統。這樣你就理解,為什么在windows平臺上,使用unicode的效率要相對更高一些。
所以,我們可以通過在一開始就是用unicode開發應用程序,使程序執行更有效率。
為了保持windows ce的精致,ms決定不支持ansi的windows函數。所以,如果要進行windows ce上的程序開發,必須了解并在整個應用程序中使用unicde。
Ms在將COM組建從16位移植到32位系統使,作出了一個決定:素有需要字符串的COM接口方法只支持unicode字符串。
標準c的string.h頭文件中個定義了一個wchar_t的unicode字符數據類型。
typdef unsigned long wchar_t;
標準c還專門為wchar_t定義了一組函數。
char* strcat(char*, const char*);
wchar_t* wcscat(wchat_t* , const wchar_t*);
size_t strlen(const char*);
size_t wcslen(const wchar_t*);
…
所有的unicode字符串都以wcs開頭,代表寬字符。為了調用unicode,簡單的將ansi字符串的str替換為wcs即可。
TChar.h頭文件主要為為了幫助ANSI/Unicode通用源代碼文件的編寫,他主要由一系列的宏組成,在編寫源代碼時,可以使用這些宏來替代對str或wcs函數直接的調用。
Ms的c++編譯器將所有的字符串默認都認為是ansi字符串,而不是unicode字符串。所以,對于下面的這句話:
TCHAR *szError =
“Error”;
如果沒有定義_UNICODE宏,則能夠編譯通過,但是如果定義了該宏,則會出現編譯錯誤。
為了生成一個UNICODE字符串而非一個ansi字符串,需要將以上的一句改為:
TCHAR *szError =
L”Error”;
那么為了同時兼容上面的兩種情況,我們定義一個宏
#ifdef _UNICODE
#define _TEXT(x) L ## x
#else
#define _TEXT(x) x
#endif
這樣我們就可以重寫以上的語句:
TCHAR* szError =
_TEXT(“Error);
WCHAR
Unicode字符
PWSTR
指向Unicode字符串的
指針
PCWSTR
指向Unicode字符串常量的指針
Windows.h中同樣定義了ansi/Unicode通用的數據類型
PTSTR
PCTSTR
在編譯這個模塊時,是否定義了UNICODE宏決定了這些數據類型指向ansi還是unicode。
注意, _UNICODE是標準c的unicode開關;
而UNICODE是windows的unicode開關。
所以,一般來說,這兩個宏要么同時定義,要么同時不定義。
在windows2000下,CreateWindowsExA只是一個簡單的轉換層,他實現內存分配并把ansi字符串轉換為unicode字符串,然后調用CreateWindowsExW函數,把轉換后unicode字符串傳遞給該函數。當CreateWindowsExW返回時,CreateWindowsExA釋放內存緩沖區,并且返回其窗口句柄。
下面是一些基本規則:
l 對于文本字符和串使用通用數據類型;
l 對字節、字節指針和數據緩沖區使用顯式數據類型;
l 對文字字符和字符串使用TEXT宏;
l 修改字符串運行問題,
使用sizeof(szbuffer)/sizeof(TCHAR)而不是sizeof(szbuffer);
l 分配內存時,使用malloc(len*sizeof(TCHAR)) 而不是malloc(len);
第一個CompareString參數指定一個32位的位置ID(LCID),用來識別具體的語言種類,CompareString使用LCID,通過檢查適用于特定語言的字符的意義來比較字符串。
sprintf()系列函數的應用
char szA[100];
wchar_t szW[100];
//normal
sprintf(szA, “%s”, “ANSI Str”);
//convert Unicode to ansi
sprintf(szA, “%S”, L”ANSI Str”);
//normal
swprintf(szW, L“%s, L”ANSI Str”);
//convert Ansi To unicode
swprintf(szW, L”%S”, “ANSI Str”);
這里要注意格式化字符串的中s字符的大小寫;
Vc程序的內部資源字符串其實也是unicode的,在使用LoadString來加載資源時,如果是ansi,則其實是現將內部的unicode轉換為ansi,然后在返回。
DWORD
IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);
用于判斷指定的文本為ansi還是unicode;
這個函數使用的是統計的方法論來分析緩沖區內的文本是ansi還是unicode,所以他也有可能返回一個錯誤的結果。
這里其實就是涉及到兩個函數
WideCharToMultiByte()
MultiByteToWideChar()
通過查看函數的原型,我們可以發現WideCharToMulteByte比MultiByteToWideChar多了兩個參數,pDefaultChar, pfUsedDefaultChar,如果寬字符不能轉換某字符,則函數應該使用參數pDefaultChar指向的字符,如果該參數為NULL,函數使用系統默認的字符。默認的字符為問號(這就是為什么在英文系統下,中文字符總是顯示為問號的原因),問號用于文件名是危險的,因為問好是一種通配符。