如果調(diào)用任何windows函數(shù),并傳遞給他一個ANSI字符串,系統(tǒng)會先將這個字符串轉(zhuǎn)換為unicode字符串,然后將這個unicode字符串傳遞給操作系統(tǒng)。這樣你就理解,為什么在windows平臺上,使用unicode的效率要相對更高一些。
所以,我們可以通過在一開始就是用unicode開發(fā)應(yīng)用程序,使程序執(zhí)行更有效率。
為了保持windows ce的精致,ms決定不支持ansi的windows函數(shù)。所以,如果要進(jìn)行windows ce上的程序開發(fā),必須了解并在整個應(yīng)用程序中使用unicde。
Ms在將COM組建從16位移植到32位系統(tǒng)使,作出了一個決定:素有需要字符串的COM接口方法只支持unicode字符串。
標(biāo)準(zhǔn)c的string.h頭文件中個定義了一個wchar_t的unicode字符數(shù)據(jù)類型。
typdef unsigned long wchar_t;
標(biāo)準(zhǔn)c還專門為wchar_t定義了一組函數(shù)。
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開頭,代表寬字符。為了調(diào)用unicode,簡單的將ansi字符串的str替換為wcs即可。
TChar.h頭文件主要為為了幫助ANSI/Unicode通用源代碼文件的編寫,他主要由一系列的宏組成,在編寫源代碼時,可以使用這些宏來替代對str或wcs函數(shù)直接的調(diào)用。
Ms的c++編譯器將所有的字符串默認(rèn)都認(rèn)為是ansi字符串,而不是unicode字符串。所以,對于下面的這句話:
TCHAR *szError =
“Error”;
如果沒有定義_UNICODE宏,則能夠編譯通過,但是如果定義了該宏,則會出現(xiàn)編譯錯誤。
為了生成一個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通用的數(shù)據(jù)類型
PTSTR
PCTSTR
在編譯這個模塊時,是否定義了UNICODE宏決定了這些數(shù)據(jù)類型指向ansi還是unicode。
注意, _UNICODE是標(biāo)準(zhǔn)c的unicode開關(guān);
而UNICODE是windows的unicode開關(guān)。
所以,一般來說,這兩個宏要么同時定義,要么同時不定義。
1.3.3 Windows系統(tǒng)中的unicode函數(shù)和ansi函數(shù)
在windows2000下,CreateWindowsExA只是一個簡單的轉(zhuǎn)換層,他實現(xiàn)內(nèi)存分配并把ansi字符串轉(zhuǎn)換為unicode字符串,然后調(diào)用CreateWindowsExW函數(shù),把轉(zhuǎn)換后unicode字符串傳遞給該函數(shù)。當(dāng)CreateWindowsExW返回時,CreateWindowsExA釋放內(nèi)存緩沖區(qū),并且返回其窗口句柄。
下面是一些基本規(guī)則:
l 對于文本字符和串使用通用數(shù)據(jù)類型;
l 對字節(jié)、字節(jié)指針和數(shù)據(jù)緩沖區(qū)使用顯式數(shù)據(jù)類型;
l 對文字字符和字符串使用TEXT宏;
l 修改字符串運行問題,
使用sizeof(szbuffer)/sizeof(TCHAR)而不是sizeof(szbuffer);
l 分配內(nèi)存時,使用malloc(len*sizeof(TCHAR)) 而不是malloc(len);
第一個CompareString參數(shù)指定一個32位的位置ID(LCID),用來識別具體的語言種類,CompareString使用LCID,通過檢查適用于特定語言的字符的意義來比較字符串。
sprintf()系列函數(shù)的應(yīng)用
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程序的內(nèi)部資源字符串其實也是unicode的,在使用LoadString來加載資源時,如果是ansi,則其實是現(xiàn)將內(nèi)部的unicode轉(zhuǎn)換為ansi,然后在返回。
DWORD
IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);
用于判斷指定的文本為ansi還是unicode;
這個函數(shù)使用的是統(tǒng)計的方法論來分析緩沖區(qū)內(nèi)的文本是ansi還是unicode,所以他也有可能返回一個錯誤的結(jié)果。
這里其實就是涉及到兩個函數(shù)
WideCharToMultiByte()
MultiByteToWideChar()
通過查看函數(shù)的原型,我們可以發(fā)現(xiàn)WideCharToMulteByte比MultiByteToWideChar多了兩個參數(shù),pDefaultChar, pfUsedDefaultChar,如果寬字符不能轉(zhuǎn)換某字符,則函數(shù)應(yīng)該使用參數(shù)pDefaultChar指向的字符,如果該參數(shù)為NULL,函數(shù)使用系統(tǒng)默認(rèn)的字符。默認(rèn)的字符為問號(這就是為什么在英文系統(tǒng)下,中文字符總是顯示為問號的原因),問號用于文件名是危險的,因為問好是一種通配符。