不管什麼時候,只要COM方法返回一個串,這個串都是Unicode串(這裡指的是寫入COM規範的所有方法)。Unicode是一種字元編碼集,類似ASCII,但用兩個位元組表示一個字元。如果你想更好地控制或操作串的話,應該將它轉換成TCHAR類型串。
TCHAR和以_t開頭的函數(如_tcscpy())被設計用來讓你用相同的原始碼處理Unicode和ANSI串。在大多數情況下編寫的代碼都是用來處理ANSI串和ANSI WindowsAPIs。你應該熟練掌握TCHAR類型,尤其是當你閱讀其他人寫的有關代碼時,要特別注意TCHAR類型。
當你從某個COM方法返回得到一個Unicode串時,可以用下列幾種方法之一將它轉換成char類型串:
1、調用 WideCharToMultiByte() API。
2、調用CRT 函數wcstombs()。
3、使用CString 構造器或賦值操作(僅用於MFC )。
4、使用ATL 串轉換宏。
1.WideCharToMultiByte()
你可以用WideCharToMultiByte()將一個Unicode串轉換成一個ANSI串。此函數的原型如下:
int WideCharToMultiByte (
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar );
以下是參數解釋:
CodePage
Unicode字元轉換成的字碼頁。你可以傳遞CP_ACP來使用當前的ANSI字碼頁。字碼頁是256個字元集。字元0――127與ANSI編碼一樣。字元128――255與ANSI字元不同,它可以包含圖形字元或者讀音符號。每一種語言或地區都有其自己的字碼頁,所以使用正確的字碼頁對於正確地顯示重音字元很重要。
dwFlags
dwFlags 確定Windows如何處理“複合” Unicode字元,它是一種後面帶讀音符號的字元。如è就是一個複合字元。如果這些字元在CodePage參數指定的字碼頁中,不會出什麼事。否則,Windows必須對之進行轉換。
傳遞WC_COMPOSITECHECK使得這個API檢查非映射複合字元。
傳遞WC_SEPCHARS使得Windows將字元分為兩段,即字元加讀音,如e`。
傳遞WC_DISCARDNS使得Windows丟棄讀音符號。
傳遞WC_DEFAULTCHAR使得Windows用lpDefaultChar參數中說明的預設字元替代複合字元。
預設行為是WC_SEPCHARS。
lpWideCharStr
要轉換的Unicode串。
cchWideChar
lpWideCharStr在Unicode 字元中的長度。通常傳遞-1,表示這個串是以0x00結尾。
lpMultiByteStr
接受轉換的串的字元緩衝
cbMultiByte
lpMultiByteStr的位元組大小。
lpDefaultChar
可選――當dwFlags包含WC_COMPOSITECHECK | WC_DEFAULTCHAR並且某個Unicode字元不能被映射到同等的ANSI串時所傳遞的一個單字元ANSI串,包含被插入的“預設”字元。可以傳遞NULL,讓API使用系統預設字元(一種寫法是一個問號)。
lpUsedDefaultChar
可選――指向BOOL類型的一個指標,設定它來表示是否預設字元曾被插入ANSI串。可以傳遞NULL來忽略這個參數。
下面就給出了如何使用這個API的例子:
// 假設已經有了一個Unicode 串 wszSomeString...
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, // ANSI 字碼頁
WC_COMPOSITECHECK, // 檢查重音字元
wszSomeString, // 原Unicode 串
-1, // -1 意思是串以0x00結尾
szANSIString, // 目的char字串
sizeof(szANSIString), // 緩衝大小
NULL, // 肥預設字串
NULL ); // 忽略這個參數
調用這個函數後,szANSIString將包含Unicode串的ANSI版本。
2,wcstombs()
這個CRT函數wcstombs()是個簡化版,但它終結了WideCharToMultiByte()的調用,所以最終結果是一樣的。其原型如下:
size_t wcstombs (
char* mbstr,
const wchar_t* wcstr,
size_t count );
以下是參數解釋:
mbstr
接受結果ANSI串的字元(char)緩衝。
wcstr
要轉換的Unicode串。
count
mbstr參數所指的緩衝大小。
wcstombs()在它對WideCharToMultiByte()的調用中使用WC_COMPOSITECHECK | WC_SEPCHARS標誌。用wcstombs()轉換前面例子中的Unicode串,結果一樣:
wcstombs ( szANSIString, wszSomeString, sizeof(szANSIString) );
3.CString
MFC中的CString包含有建構函式和接受Unicode串的賦值操作,所以你可以用CString來實現轉換。例如:
// 假設有一個Unicode串wszSomeString...
CString str1 ( wszSomeString ); // 用構造器轉換
CString str2;
str2 = wszSomeString; // 用賦值操作轉換
4.ATL宏
ATL有一組很方便的宏用於串的轉換。W2A()用於將Unicode串轉換為ANSI串(記憶方法是“wide to ANSI”――寬字元到ANSI)。實際上使用OLE2A()更精確,“OLE”表示的意思是COM串或者OLE串。下面是使用這些宏的例子:
#include <atlconv.h>
// 還是假設有一個Unicode串wszSomeString...
{
char szANSIString [MAX_PATH];
USES_CONVERSION; // 聲明這個宏要使用的局部變數
lstrcpy ( szANSIString, OLE2A(wszSomeString) );
}
OLE2A()宏“返回”轉換的串的指標,但轉換的串被儲存在某個臨時棧變數中,所以要用lstrcpy()來獲得自己的拷貝。其它的幾個宏是W2T()(Unicode 到 TCHAR)以及W2CT()(Unicode到常量TCHAR串)。
有個宏是OLE2CA()(Unicode到常量char串),可以被用到上面的例子中,OLE2CA()實際上是個更正宏,因為lstrcpy()的第二個參數是一個常量char*,關於這個問題本文將在以後作詳細討論。
另一方面,如果你不想做以上複雜的串處理,儘管讓它還保持為Unicode串,如果編寫的是控制台應用程式,輸出/顯示Unicode串時應該用全程變數std::wcout,如:
wcout << wszSomeString;
但是要記住,std::wcout只認Unicode,所以你要是“正常”串的話,還得用std::cout輸出/顯示。對於Unicode串文字量,要使用首碼L標示,如:
wcout << L"The Oracle says..." << endl << wszOracleResponse;
如果保持串為Unicode,編程時有兩個限制:
―― 必須使用wcsXXX() Unicode串處理函數,如wcslen()。
―― 在Windows 9x環境中不能在Windows API中傳遞Unicode串。要想編寫能在9x和NT上都能啟動並執行應用,必須使用TCHAR類型,詳情請參考MSDN。
字串類型定義
A ANSI character string.
W Unicode character string.
T Generic character string (equivalent to W when _UNICODE is defined, equivalent to A otherwise).
OLE OLE character string (equivalent to W).
關於中文寬字元的轉換
我用mbstowbs函數轉換不行,不能轉換中文
後用LPCOLESTR pwzStr = T2COLE(LPCSTR pszStr)
轉換成功
用法:
#include <atlconv.h>
USES_CONVERSION;
LPCOLESTR pwzStr = T2COLE(LPCSTR pszStr);