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