Posted on 2008-04-16 15:28
orlando 閱讀(161)
評論(0) 編輯 收藏 引用
由于作者是美國人的緣故,我發現Windows下的幾本名著(如《Windows程序設計》,Jeffrey Richter的《Windows 核心編程》)對字符集的講解都不甚透徹。現在這里對一些易讓人迷惑的問題進行澄清,并指明一些編程時容易出錯的問題(我自己就犯過)。
先解釋幾個概念:
字符集:根據編碼特性而分,字符集可分為三類。
l 窄字符集(SBCS) 每個代碼由一個字節進行表示,比如ANSI。
l 多字節字符集(MBCS) 字符集中的代碼或者是單字節,或者是多字節,比如DBCS,GB2312等。
l 寬字節字符集 字符集中每個字符由兩個字節表示。比如UNICODE
代碼頁:在UNICODE和DBCS中由于包含的代碼十分多,為了使用方便就需要對這些代碼進行組織。組織的方法就是把不同國家的代碼分別放入不同的代碼頁。
字符集與代碼頁的關系:由上可知,對于UNICODE和DBCS,代碼頁是從屬于字符集的。但對于SBCS類的字符集(比如ANSI)和DBCS之外的MBCS字符集(比如GB2312等)他們則只對應于一個代碼頁。
下面看一段潛在有問題的程序:
void ConverAndOutputString(HDC hdc,LPWSTR wstr, int length,int x,int y)
{
int nret;
int sizebuffer= 2*length;
char* lpBuffer=new char[sizebuffer];
nret=WideCharToMultiByte(CP_ACP,0,wstr , length,
lpBuffer, sizebuffer ,NULL,NULL);
TextOut(hdc,x,y, lpBuffer,nret);
delete[]lpBuffer;
}
這段程序很簡單,只是把一個寬字符串轉為DBCS串而后按指定的坐標進行輸出。Jeffrey Richter在他的《Windows核心編程》中的第26頁也用幾乎的相同的方法進行字符串轉換。但這段程序其實是有問題的。問題出在轉換字符串時不應該硬編碼指定代碼頁,而應該根據當前字體進行動態獲取。否則在某些情況下將無法把wstr中的UNICODE字符轉換到正確的代碼。如果你用上述代碼進行中文輸出,你將很有幸看到很多問號被自動添加到你的字符串中。
解決的辦法也很簡單,但首先你要熟悉如下兩個個API函數:
int GetTextCharset(HDC hdc);//lpCs,dwFlags