繼上集故事《多字元集(ANSI)和UNICODE及字串處理方式準則
》,我們現在有一些特殊需求:
有時候我們的字串是多字元型,我們卻需要使用寬字元型;有的時候卻恰恰相反。
Windows為我們提供了這樣的函數來處理這個問題:
1.MultiByteToWideChar
函數功能:
該函數映射一個字串到一個寬字元 (unicode)的字串。由該函數映射的字串沒必要是多位元組字元組。
函數原型:
int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte,
LPWSTR lpWideCharStr, int cchWideChar);
參數:
CodePage:指定執行轉換的字碼頁,這個參數可以為系統已安裝或有效任何字碼頁所給定的值。你也 可以指定其為下面的任意一值:
CP_ACP:ANSI字碼頁;CP_MACCP:Macintosh代碼 頁;CP_OEMCP:OEM字碼頁;
CP_SYMBOL:符號字碼頁(42);CP_THREAD_ACP:當前線程ANSI代碼 頁;
CP_UTF7:使用UTF-7轉換;CP_UTF8:使用UTF-8轉換。
dwFlags:一組位標記用以指出是否未轉換成預作或寬字元(若組合形式存在),是否使用象 形文字替代控制字元,以及如何處理無效字元。你可以指定下面是標記常量的組合,含義如下:
MB_PRECOMPOSED:通常使用預作字元——就是說,由一個基底字元和一個非Null 字元組 成的字元只有一個單一的字元值。這是預設的轉換選擇。不能與
MB_COMPOSITE值一起使用。
MB_COMPOSITE:通常使用組合字元——就是說,由一個基底字元和一個非Null 字元組成的 字元分別有不同的字元值。不能與MB_PRECOMPOSED值一起使用。
MB_ERR_INVALID_CHARS:如果函數遇到無效的輸入字元,它將運行失敗,且 GetLastErro返回ERROR_NO_UNICODE_TRANSLATION值。
MB_USEGLYPHCHARS:使用表意字元替代控制字元。
組合字元由一個基礎字元和一個非Null 字元構成,每一個都有不同的字元值。每個預作字元都有單一的 字元值給基礎/非Null 字元的組成。在字元è中,e就是基礎字元,而重音符標記就是非Null 字元。
函數的預設動作是轉換成預作的形式。如果預作的形式不存在,函數將嘗試轉換成組合形式。
標記MB_PRECOMPOSED和MB_COMPOSITE是互斥的,而標記 MB_USEGLYPHCHARS和MB_ERR_INVALID_CHARS則不管其它標記如何都可以設定。
lpMultiByteStr:指向將被轉換字串的字元。
cchMultiByte:指定由參數lpMultiByteStr指向的字串中位元組的個 數。如果這個值為-1,字串將被設定為以NULL為結束符的字串,並且自動計算長度。
lpWideCharStr:指向接收被轉換字串的緩衝區。
cchWideChar:指定由參數lpWideCharStr指向的緩衝區的位元組個數。若此 值為零,函數返回緩衝區所必需的寬字元數,在這種情況下,lpWideCharStr中的緩衝區不被使用。
傳回值
如果函數運行成功,並且cchWideChar不為零,傳回值是由lpWideCharStr指向的緩 沖區中寫入的寬字元數;如果函數運行成功,並且cchMultiByte為零,傳回值是接收到待轉換字串的緩衝區所需求的寬字元數大小。如果函數運行失 敗,傳回值為零。若想獲得更多錯誤資訊,請調用GetLastError函數。它可以返回下面所列錯誤碼:
ERROR_INSUFFICIENT_BUFFER;ERROR_INVALID_FLAGS;
ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。
注意
指標lpMultiByteStr和lpWideCharStr必須不一樣。如果一樣,函數將失 敗,GetLastError將返回ERROR_INVALID_PARAMETER的值。
如果MB_ERR_INVALID_CHARS被設定並且在資源字串中遇到無效的字元時,函 數將失敗。如果MB_ERR_INVALID_CHARS不被設定,或是DBCS串中發現了頭位元組而沒有有效尾位元組,無效字元將轉換為預設字元,但不是 資源字串中的預設字元。當無效字元被發現,且MB_ERR_INVALID_CHARS值被設定,函數返回零,GetLastErro顯示 ERROR_NO_UNICODE_TRANSLATION的出錯資訊。
2.WideCharToMultiByte
函數功能:
該函數映射一個unicode字串到一個多位元組字串。
函數原型:
int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPWSTR lpWideCharStr, int cchWideChar, LPCSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, PBOOL pfUsedDefaultChar );
參數:
CodePage:指定執行轉換的字碼頁,這個參數可以為系統已安裝或有效任 何字碼頁所給定的值。你也可以指定其為下面的任意一值:
CP_ACP:ANSI字碼頁;CP_MACCP:Macintosh代碼 頁;CP_OEMCP:OEM字碼頁;
CP_SYMBOL:符號字碼頁(42);CP_THREAD_ACP:當前線索ANSI代碼 頁;
CP_UTF7:使用UTF-7轉換;CP_UTF8:使用UTF-8轉換。
dwFlags [in] Specifies the handling of unmapped characters. The function performs more quickly when none of these flags is set. The following flag constants are defined.
Value
|
Meaning
|
WC_NO_BEST_FIT_CHARS
|
Windows 98/Me and Windows 2000/XP: Any Unicode characters that do not translate directly to multibyte equivalents are translated to the default character (see lpDefaultChar parameter). In other words, if translating from Unicode to multibyte and back to Unicode again does not yield the exact same Unicode character, the default character is used. This flag can be used by itself or in combination with the other dwFlag options.
|
WC_COMPOSITECHECK
|
Convert composite characters to precomposed characters.
|
WC_DISCARDNS
|
Discard nonspacing characters during conversion.
|
WC_SEPCHARS
|
Generate separate characters during conversion. This is the default conversion behavior.
|
WC_DEFAULTCHAR
|
Replace exceptions with the default character during conversion.
|
When WC_COMPOSITECHECK is specified, the function converts composite characters to precomposed characters. A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/nonspacing character combination. In the character , the e is the base character, and the accent grave mark is the nonspacing character.
When an application specifies WC_COMPOSITECHECK, it can use the last three flags in this list (WC_DISCARDNS, WC_SEPCHARS, and WC_DEFAULTCHAR) to customize the conversion to precomposed characters. These flags determine the function's behavior when there is no precomposed mapping for a base/nonspace character combination in a wide-character string. These last three flags can only be used if the WC_COMPOSITECHECK flag is set.
The function's default behavior is to generate separate characters (WC_SEPCHARS) for unmapped composite characters.
For the code pages in the following table, dwFlags must be zero, otherwise the function fails with ERROR_INVALID_FLAGS.
50220 50221
50222
50225
|
50227 50229
52936
54936
|
57002 through 57011 65000 (UTF7)
65001 (UTF8)
42 (Symbol)
|
相關變數
lpWideCharStr:指向將被轉換的unicode字串。
cchWideChar:指定由參數lpWideCharStr指向的緩衝區的 字元個數。如果這個值為-1,字串將被設定為以NULL為結束符的字串,並且自動計算長度。
lpMultiByteStr:指向接收被轉換字串的緩衝區。
cchMultiByte:指定由參數lpMultiByteStr指向的緩衝 區最大值(用位元組來計量)。若此值為零,函數返回lpMultiByteStr指向的目標緩衝區所必需的位元組數,在這種情況 下,lpMultiByteStr參數通常為NULL。
lpDefaultChar和pfUsedDefaultChar: 只有當WideCharToMultiByte函數遇到一個寬位元組字元,而該字元在uCodePage參數標識的字碼頁中並沒有它的標記法 時,WideCharToMultiByte函數才使用這兩個參數。如果寬位元組字元不能被轉換,該函數便使用lpDefaultChar參數指向的字元。 如果該參數是NULL(這是大多數情況下的參數值),那麼該函數使用系統的預設字元。該預設字元通常是個問號。這對於檔案名稱來說是危險的,因為問號是個通 配符。pfUsedDefaultChar參數指向一個布爾變數,如果Unicode字串中至少有一個字元不能轉換成等價多位元組字元,那麼函數就將該變 量置為TRUE。如果所有字元均被成功地轉換,那麼該函數就將該變數置為FALSE。當函數返回以便檢查寬位元組字串是否被成功地轉換後,可以測試該變 量。
傳回值:
如果函數運行成功,並且cchMultiByte不為零,傳回值是由 lpMultiByteStr指向的緩衝區中寫入的位元組數;如果函數運行成功,並且cchMultiByte為零,傳回值是接收到待轉換字串的緩衝區所 必需的位元組數。如果函數運行失敗,傳回值為零。若想獲得更多錯誤資訊,請調用GetLastError函數。它可以返回下面所列錯誤碼:
ERROR_INSUFFICIENT_BJFFER;ERROR_INVALID_FLAGS;
ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。
注意:
指標lpMultiByteStr和lpWideCharStr必須不一樣。如果一樣, 函數將失敗,GetLastError將返回ERROR_INVALID_PARAMETER的值。
除此之外,還有幾個比較有意思的字串處理函數:
1.GetTextCharsetInfo
函數功能:
返回關於選入指定的裝置描述表內的當前字型資訊。
函數原型
int GetTextCharsetInfo(
__in HDC hdc,
__out LPFONTSIGNATURE lpSig,
__in DWORD dwFlags
);
參數
hdc
[in] 裝置描述表的控制代碼。
lpSig
[out] 可選。指向一個 FONTSIGNATURE 資料結構的指標,該指標接收字型簽名資訊。
如果一個 True Type 字型被選入當前的設別描述表,結構會接收能夠標識編碼頁和Unicode 子範圍的字型符號。
如果字型不是 True Type ,則結構會接收到0.此時,應用程式應使用 TranslateCharsetInfo 函數來獲得原始的字型簽名。
如果應用程式不需要 FONTSIGNATURE 資訊時,可以將該參數設為NULL。此時,應用程式也可以調用GetTextCharset 函數,而且調用該函數與調用GetTextCharset函數是一個效果。
dwFlags
[in] 保留。必須為0.
傳回值
如果超過,返回一個值用來標識選入裝置描述表內的字型的字元集資訊。如果函數失敗,傳回值是 DEFAULT_CHARSET.
2.GetTextCharset
函數功能:
此函數擷取當前選進的裝置描述表的字元集,等同於GetTextCharsetInfo(hdc, NULL, 0)。
函數原型:
int GetTextCharset( HDC hdc );
傳回值:
成功返回字元集標識,失敗返回DEFAULT_CHARSET。
3.BOOL IsDBCSLeadByte( BYTE TestChar );
此函數使用當前WindowsANSI字碼頁判斷指定位元組是不是一個潛在的雙位元組字元(DBCS)的引導位元組。若使用其他字碼頁,請用
IsDBCSLeadByteEx函數。
4.BOOL IsDBCSLeadByteEx( UINT CodePage, BYTE TestChar );
此函數判斷指定位元組是不是一個潛在的雙位元組字元(DBCS)的引導位元組。
CodePage可用的值有:CP_ACP,CP_MACCP,CP_OEMCP,CP_THREAD_ACP。
5.
BOOL IsTextUnicode( CONST VOID* pBuffer, int cb, LPINT lpi );
此函數判斷指定緩衝區裡是否可能會有某種格式的Unicode文本。這個函數判斷方式並不準確,所以可能會返回錯誤結果。記事本就是使用
了這個函數,所以有時候會出現亂碼。所以請謹慎使用這個函數。
還有三個Windows不推薦使用的函數:NlsDllCodePageTranslation,UnicodeToBytes和BytesToUnicode,此處不作過多介紹了。
其中,我們重點關注的還是MultiByteToWideChar和WideCharToMultiByte這兩個函數,具體這兩個函數的使用方式,
請關注下集故事《讓你的程式更加適用——使用ANSI和UNICODE匯出函數》
同系列文章參看:
《多字元集(ANSI)和UNICODE及字串處理方式準則》
《
讓你的程式更加適用——使用ANSI和UNICODE匯出函數
》