Unicode——Windows核心编程学习手札之二
Unicode
——Windows核心編程學習手札之二
處理軟件本地化的核心在于處理不同的字符集。文本串一直作為一系列單字節字符進行編碼,并在結尾處放上一個零,當調用strlen函數時,獲取以/0結尾的單字節字符數組中返回字符的數目。但各地的文字和書寫規則單字節(256個字符)可能不夠使用,因此需要雙字節字符集(DBCS)的支持。雙字節字符集,字符串中的每個字符可以包含一個字節或兩個字節,對于程序員來說是個難題。
為此,Unicode標準被提出來。Unicode字符串中的所有字符都是16位的(兩個字節)。也就是說固定了雙字節來表示一個字符。Unicode用16位值表示每個字符,總共可以得到65000個字符,能夠滿足對各地不同的文字和書寫規則字符所需。Unicode字符集具有:容易在不同語言之間進行數據交換;能夠分配支持所有語言的單個二進制EXE文件或DLL文件;提高應用程序的效率。
Windows2000是使用Unicode從頭開發進行,用于創建窗口、顯示文本、進行字符串操作等的所有核心函數都需要Unicode字符串。如果調用任何一個Windows函數并給它傳遞一個ANSI字符串,系統首先會先該字符串轉換成Unicode,然后將Unicode傳遞給操作系統。如調用CreateWindowEx函數,并傳遞類名字和窗口標題文本的非Unicode字符串,那么CreateWindowEx必須分配內存塊(在進程默認堆中),將非Unicode字符串轉換成Unicode字符串,并將結果存儲到分配的內存塊中,然后調用Unicode版的CreateWindowEx函數。由于系統必須執行這些轉換操作,這些渙渙操作是在你看不見的情況下完成,需要更多的內存,并且運行速度較慢,因此開發基于Windows2000操作系統的應用程序最后從頭開始就使用Unicode,可以使應用程序更加有效地運行。
Windows98繼承16位Windows操作系統特性,不是用Unicode來處理,不過同樣可以處理Unicode字符和字符串,如同Windows2000處理非Unicode字符串一樣。如調用CreateWindowEx函數并將Unicode字符串傳遞給它,就必須明確分配緩存以便執行從Unicode到ANSI字符串的轉換操作,當調用CreateWindowEx函數返回時,就釋放臨時緩存。
Windows2000既支持Unicode也支持ANSI,可以為任意一種開發應用程序;而Windows98只支持ANSI,只能為ANSI開發應用程序。Microsoft在將COM從16位Windows轉換成Win32時,將需要字符串的所有COM接口方法改成只能接受Unicode字符串,因為COM通常用于不同組件間進行通信,Unicode是傳遞字符串最佳手段。Microsoft為Unicode設計了Windows API可以盡量減少對代碼的影響。在編寫單個源代碼文件,可以通過定義宏(UNICODE和_UNICODE)確定使用或不使用Unicode來進行編譯。
為了利用Unicode字符串,C運行期庫定義了一些數據類型。標準的C頭文件String.h中定義了一個Unicode字符數據類性,名字為wchar_t的數據類型:
Typedef unsigned short wchar_t;
如你要創建一個緩存,用于存放最多為99個字符的Unicode字符串和一個結尾為零,可以使用下面語句:
wchar_t szBuffer[100];
該語句創建了一個由100個16位值組成的數組。標準的C運行期庫字符串函數,如strcpy、strchr、strcat等只能對ANSI字符串進行操作,不能正確處理Unicode字符串。因此,ANSI C也設計了一組補充函數用于出來Unicode,如char *strcat(char *,const char*)處理ANSI字符串,對應的Unicode字符串函數是wchar_t *wcscat(wchar_t *,const wchar_t),一般所有的Unicode函數均以wcs開頭。ANSI C規定,C運行期庫支持Unicode字符和字符串。若要建立支持ANSI/UNICODE通用代碼,需要包含TChar.h文件而非String.h文件。TChar.h包含用在源代碼中的一組宏,而不直接調用str函數或wcs函數。如果在編譯文件中定義了_UNICODE,這些宏就用wcs組函數,如沒有定義,則引用str這組宏。如在TChar.h中有一個宏_tcscpy,如在頭文件中沒有定義_UNICODE,那_tcscpy就擴展為ANSI的strcpy函數,如定義了,則擴展為Unicode的wcscpy函數。
Windows頭文件定義的Unicode數據類型有:WCHAR Unicode字符串;PWSTR 指向Unicode字符串的指針;PCWSTR 指向一個恒定的Unicode字符串的指針。Windows頭文件也定義了ANSI和UNICODE通用數據類型PTSTR和PCTSTR,這些數據類型既可以指ANSI字符串,也可以指Unicode字符串,取決于編譯程序模塊是否定義了UNICODE宏,這里宏和C運行期頭文件定義的_UNICODE宏不一樣。
Windows還提供一組字符串操作函數,與C運行期字符串函數(如strcpy和wcscpy)相似,但這些函數是操作系統的組成部分,操作系統的許多組件都使用這些函數而不使用C運行期庫。建立最好使用操作系統函數而不使用C運行期庫字符串函數,這有助于提高應用程序的運行性能,因為操作系統字符串函數常常被大型應用程序如操作系統的外殼進程Explorer.exe所使用,由于這些函數使用多,在你應用程序運行時,它們很可能已經被裝入了RAM中。
開發符合ANSI和Unicode的應用程序,需要遵循的原則:將文本串視為字符數組而不是chars數組或字節數組;將通用數據類型(如TCHAR和PTSTR)用于文本字符和字符串;將顯示數據類型(如BYTE和PBYTE)用于字節、自己指針和數據緩存;將TEXT宏用于原義字符和字符串;執行全局性替換(例如用PTSTR替換PSTR);修改字符串運算問題。如果開發包含C運行期庫頭文件,Unicode宏定義為_UNICODE,如果定義了則編譯時如果是通用數據類型和函數則選擇執行Unicode函數,同樣如果在Windows頭文件中定義UNICODE宏處理是一樣。要開發出符合ANSI和Unicode的應用程序需要在代碼中用通用數據類型和函數來處理字符和字符串,如果在代碼中直接使用了ANSI的函數和數據類型,那么就算宏定義了Unicode也將只能處理ANSI字符和字符串,對于Unicode是一樣。考慮到利用宏定義就可以實現ANSI和Unicode的應用程序切換。
這里做了個代碼測試,在Visual C++6.0開發環境中,建立一個Win32 Console Application,并在Project Settings中的C/C++頁Preprocessor definitions里添加UNICODE的宏,同時在主文件中加入頭文件#include <windows.h>并執行如下代碼觀察:
#include "stdafx.h"
#include <windows.h>
int main(int argc, char* argv[])
{
?????? TCHAR ch[]=TEXT("ANSI or Unicode");
?????? int it=sizeof(ch);
?????? int it1=sizeof(TCHAR);
?????? int? ilen=sizeof(ch)/sizeof(TCHAR);
?????? printf("%d,%d,%d/n",it,it1,ilen);
?????? return 0;
}
可發現it=32,it1=2,ilen=16;回到Project Settings中的C/C++頁Preprocessor definitions中取消UNICODE宏,再次執行代碼發現it=16,it1=1,ilen=16;這就說明了宏定義對ANSI/UNICODE通用數據類型的取決作用,如果定義了UNICODE宏,那么TCHAR就是char類型,單字節,沒有定義UNICODE宏則是wchar_t,雙字節。
???????????????????????? 如非
???????????????????????????? 2008-11-25
總結
以上是生活随笔為你收集整理的Unicode——Windows核心编程学习手札之二的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人在江湖
- 下一篇: 对程序错误的处理——Windows核心编