国际化开发技术FAQ
什么是國際化開發(fā)?
答:指應(yīng)用程序能夠支持不同的語言輸入和顯示,同時(shí)也能夠自如的適應(yīng)不同文化的習(xí)俗。
?
字節(jié)、字符、字符集和字符集編碼的關(guān)系?
答:計(jì)算機(jī)底層處理的最小單位是字節(jié)(8 位二進(jìn)制表示)。
字符是表示一個(gè)有意義的符號或文字。
字符集是由一組相關(guān)的字符所組成的集合。比如說德文字符集只與德文相關(guān),中文字符集只與中文相關(guān),不會(huì)互相包含。
字符集編碼是解決字符在計(jì)算機(jī)中的編碼問題。
?
如何將字符集進(jìn)行分類?
答:字符集編碼通常可以分為以下3 種:單字節(jié)編碼、寬字符編碼和多字節(jié)字符編碼。
??? 按照c/c++ 習(xí)慣,還可以分為:ANSI 字符集(單個(gè)/0 字符結(jié)尾)和寬字符集。
?
什么是 gb2312 字符集?
答:由原中國國家標(biāo)準(zhǔn)總局發(fā)布,1981 年5 月1 日實(shí)施,是中國國家標(biāo)準(zhǔn)的簡體中文字符集。它收錄了漢字及一般符號、序號、數(shù)字、拉丁字母、日文假名、希臘字母、俄文字母、漢語拼音符號、漢語注音字母,共7445 個(gè)圖形字符。
?
什么是 gbk 字符集?
答:GBK 最初是由微軟對GB2312 的擴(kuò)展,也就是CP936 字碼表 (Code Page 936) 的擴(kuò)展(原來的CP936 和GB 2312-80 一模一樣),最初出現(xiàn)于Windows 95 簡體中文版中,由于Windows 產(chǎn)品的流行和在大陸廣泛被使用,中華人民共和國國家有關(guān)部門將其作為技術(shù)規(guī)范。注意GBK 并非國家正式標(biāo)準(zhǔn),只是國家技術(shù)監(jiān)督局標(biāo)準(zhǔn)化司、電子工業(yè)部科技與質(zhì)量監(jiān)督司發(fā)布的“技術(shù)規(guī)范指導(dǎo)性文件”。雖然 GBK 收錄了所有Unicode 1.1 及GB 13000.1-93 之中的漢字,但是編碼方式與Unicode 1.1 及GB 13000.1-93 不同。僅僅是GB 2312 到GB 13000.1-93 之間的過渡方案。GBK 收錄了21886 個(gè)符號,它分為漢字區(qū)和圖形符號區(qū)。漢字區(qū)包括21003 個(gè)字符。
?
什么是 GB18030 字符集?
答: 2000 年的GB18030 取代了GBK1.0 的正式國家標(biāo)準(zhǔn)。該標(biāo)準(zhǔn)收錄了27484 個(gè)漢字,同時(shí)還收錄了藏文、蒙文、維吾爾文等主要的少數(shù)民族文字。現(xiàn)在的PC 平臺必須支持GB18030 ,對嵌入式產(chǎn)品暫不作要求。所以手機(jī)、MP3 一般只支持GB2312 。
?
什么是 BIG5 字符集?
答: 大五碼(Big5 ),又稱為五大碼,是使用繁體 中文社群中最常用的電腦漢字字符集 標(biāo) 準(zhǔn),共收錄13,060 個(gè)中文字,其中有二字為重覆編碼,Big5 屬中文內(nèi)碼(中文碼分為中文內(nèi)碼及中文交換碼兩類)。Big5 雖普及于臺灣、香港與澳門 等繁體中文通行區(qū),但長期以來并非當(dāng)?shù)氐膰覙?biāo)準(zhǔn),而只是業(yè)界標(biāo)準(zhǔn)(de facto standard )。倚天中文系統(tǒng)、Windows 等主要系統(tǒng)的字符集都是以Big5 為基準(zhǔn),但廠商又各自增刪,衍生成多種不同版本。
??? 2003 年,Big5 被收錄到臺灣官方標(biāo)準(zhǔn)的附錄當(dāng)中,取得了較正式的地位。這個(gè)最新版本被稱為Big5-2003 。
?
什么是 “ 許蓋功 ”問題?如何解決?
答:Big5碼 是雙字節(jié)字符集,使用了雙 字符 儲存方法,以兩個(gè)字節(jié)來安放一個(gè)字。第一個(gè)字節(jié)稱為「高位字節(jié)」,第二個(gè)字節(jié)稱為「低位字節(jié)」。“ 高位字節(jié)” 使用了0x81-0xFE ,“ 低位字節(jié)” 使用了0x40-0x7E ,及0xA1-0xFE 。
在Big5 的分區(qū)中:
| 0x8140-0xA0FE | 保留給使用者自定義字元(造字區(qū)) |
| 0xA140-0xA3BF | 標(biāo)點(diǎn)符號、希臘字母 及特殊符號, |
| 0xA3C0-0xA3FE | 保留。此區(qū)沒有開放作造字區(qū)用。 |
| 0xA440-0xC67E | 常用漢字,先按筆劃 再按部首 排序。 |
| 0xC6A1-0xC8FE | 保留給使用者自定義字元(造字區(qū)) |
| 0xC940-0xF9D5 | 次常用漢字,亦是先按筆劃再按部首排序。 |
| 0xF9D6-0xFEFE | 保留給使用者自定義字元(造字區(qū)) |
??? 如其他DBCS 字符集相同,普通ASCII (小于0x80 )采用一個(gè)字節(jié)表示,這與雙字節(jié)的低字節(jié)部分有重疊。
??? 因?yàn)榈臀?/span> 字符 中包含了程序 、shell 、script 中,字串或命令常會(huì)用到的特殊字元,例如0x5C “/” 、0x7C “|” 等。「/ 」 在許多用途的字串中是當(dāng)作轉(zhuǎn)義符號又稱為跳脫 字符 ,例如 /n (換行)、/r (歸位) 、/t (tab )、// (/ 本身符號)、/" (引號)等等。而 「| 」 在UNIX 作業(yè)系統(tǒng)中大多當(dāng)作命令管線的使用,如 "ls -la | more" 等等。如果在字串中有這些特殊的轉(zhuǎn)義字元,會(huì)被程序或編譯器解釋為特殊用途。但是因?yàn)槭侵形牡脑?#xff0c;故無法正確解釋為上面所述的行為,因此程式可能會(huì)忽略此轉(zhuǎn)義符號或是中斷執(zhí)行。若此,就違反了使用者本來要當(dāng)成中文字元一部份使用的本意。
??? 在常用字如「功」(0xA55C) 、「-( 許)- 」(0xB35C) 、「蓋」(0xBB5C) 、「育」(0xA87C) 中時(shí)常出現(xiàn),造成了許多軟體無法正確處理以Big5 編碼的字串或文件。這個(gè)問題被戲謔性地人名化,稱為「-( 許功蓋)- 」或「-( 許蓋功)- 」( 這三個(gè)字都有這種問題) 。
??? 一般的解決方法,是額外增加“/” 的字元,因?yàn)?span lang="EN-US">“//” 會(huì)被解釋為“/” ,所以“ 成功/ 因素” 這個(gè)字串就能無誤地被程式當(dāng)作“ 成功因素” 的字串來處理。 但是額外的困擾是,有些輸出功能并不會(huì)把“/” 當(dāng)作特殊字元看待,所以有些程式或網(wǎng)頁就會(huì)錯(cuò)誤地常常出現(xiàn)在「許功蓋」這些字后面多了“/” 。
?
什么是 HKSCS 字符集?
答:HKSCS 是中國香港增補(bǔ)字符集,是以big5 為基礎(chǔ)進(jìn)行擴(kuò)充的。增加了一些粵語方言字和地名等。
?
什么是 UTF-8 字符集?
答:UTF-8 (8 位元 Universal Character Set /Unicode Transformation Format )是一種針對 Unicode 的可變長度字符編碼 。它可以用來表示 Unicode 標(biāo)準(zhǔn)中的任何字符,且其編碼中的第一個(gè)字節(jié) 仍與 ASCII 相容,這使得原來處理 ASCII 字符的軟件 無須或只須做少部份修改,即可繼續(xù)使用。因此,它逐漸成為電子郵件 、網(wǎng)頁 及其他儲存 或傳送文字的應(yīng)用中,優(yōu)先采用的編碼。
?
什么是 UTF-16 字符集?
答: UTF-16 是unicode 的缺省編碼方式,不兼容ASCII 碼,所有字符都是占用兩個(gè)字節(jié)。存在大小端的問題,一般用于本地存儲和顯示。
?
什么是 UTF-32 字符集?
答: UTF-32 一般用于UCS-4 ,采用4 字節(jié)編碼方式,目前很少用到。UTF-32 與UTF-16 一樣存在大小端的問題。
什么是 BOM ?
答: Unicode 規(guī)范中推薦的標(biāo)記字節(jié)順序的方法是BOM 。BOM 不是“Bill Of Material” 的BOM 表,而是Byte Order Mark 。BOM 是一個(gè)有點(diǎn)小聰明的想法:
在UCS 編碼中有一個(gè)叫做”ZERO WIDTH NO-BREAK SPACE” 的字符,它的編碼是FEFF 。而FFFE 在UCS 中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS 規(guī)范建議我們在傳輸字節(jié)流前,先傳輸 字符”ZERO WIDTH NO-BREAK SPACE” 。
這樣如果接收者收到FEFF ,就表明這個(gè)字節(jié)流是Big-Endian 的;如果收到FFFE ,就表明這個(gè)字節(jié)流是Little-Endian 的。因此字符”ZERO WIDTH NO-BREAK SPACE” 又被稱作BOM 。
UTF-8 不需要BOM 來表明字節(jié)順序,但可以用BOM 來表明編碼方式。字符”ZERO WIDTH NO-BREAK SPACE” 的UTF-8 編碼是EF BB BF 。所以如果接收者收到以EF BB BF 開頭的字節(jié)流,就知道這是UTF-8 編碼了。
?
記事本、 UltraEdit 和 VIM 對 BOM 支持情況如何 ?
答:記事本可以自動(dòng)識別帶不帶BOM 的文本文件。
??? UltraEdit 如果在高級設(shè)置選擇了檢測UTF-8 ,則指出帶BOM 的utf-8 文件,否則亂碼。
??? Vim 支持bom 和不帶bom ,但是要在配置文件中設(shè)置:encoding=cp936 fileencodings=ucs-bom,utf-8,cp936 。
?
UNICODE 和 _UNICODE 的作用是什么 ?
答: _UNICODE 只是針對 CRT 標(biāo)準(zhǔn)庫的 unicode 定義 ,UNICODE 是針對 win32 api 的 unicode 定義。
這兩個(gè)宏的作用,就是在編譯時(shí)把相應(yīng)的標(biāo)準(zhǔn)接口替換成ansi 或unicode 版本。
如果定義了這兩個(gè)宏,vc 會(huì)編譯成unicode 版本。否則,編譯成ansi 版本。
?
?
如何編寫 unicode 程序 ?
答:通常有兩種方法:
1、 ? 代碼寫成ansi/unicode ,通過在工程中設(shè)置 UNICODE 和 _UNICODE 宏來控制是否支持 unicode 。
2、 ? 顯式定義unicdoe 變量和接口,顯式調(diào)用寬字符集標(biāo)準(zhǔn)庫接口和系統(tǒng)接口。
?
什么是 ANSI/Unicode 程序 ?
答:指同一份代碼可以編譯成ANSI 版本,也可以編譯成Unicode 版本,以便適應(yīng)不同的需求。
?
如何編寫 ANSI/Unicode 程序 ?
答:
1 、字符串變量或參數(shù)都定義成 TCHAR 、LPTSTR 或LPCTSTR 。
2 、調(diào)用標(biāo)準(zhǔn)庫或win32 的通用接口。
3、 ? 通過在工程中設(shè)置 UNICODE 和 _UNICODE 宏來控制生成 unicode 代碼或ansi 代碼。
4、 ? 對于常量字符串通過TEXT 宏來進(jìn)行自動(dòng)轉(zhuǎn)換。
?
如何使用 ansi/unicode 通用接口 ?
答:
1、 ? 對于標(biāo)準(zhǔn)庫,所有的ansi/unicode 通用接口都在tchar.h 中,每種常規(guī)的函數(shù)都有對應(yīng)的通用接口,比如:printf 對應(yīng)_tprintf 。
2、 ? 對于win32 api ,調(diào)用通用標(biāo)準(zhǔn)接口即可,因?yàn)榇蟛糠?span lang="PT-BR">win32 api 都支持ansi/unicode 。
??? 比如調(diào)用 CreateWindow ,而不是顯示調(diào)用CreateWindowA 或CreateWindowW 。
3 、
?
Windows 對 unicode 的支持情況 ?
答: windows 98 部分支持 unicode ,windows NT/2k 以后版本在內(nèi)核中完全支持 unicode 。如果你的程序要在windows 98 和windows 2k 上同時(shí)運(yùn)行,則最好寫成ansi/unicode ,在windows 98 上使用ansi 版本運(yùn)行。
Windows CE 只支持Unicode ,只能開發(fā)純unicode 應(yīng)用程序。
?
VC 的資源是否 unicode , 對加載資源有什么影響 ?
答: 源編譯器對你的所有資源進(jìn)行編譯時(shí),輸出文件是資源的二進(jìn)制文件。資源(字符串表、對話框模板和菜單等)中的字符串值總是寫作 Unicode 字符串。在 Windows 98 和 Windows 2000 下,如果應(yīng)用程序沒有定義 UNICODE 宏,那么系統(tǒng)就會(huì)進(jìn)行內(nèi)部轉(zhuǎn)換。
?????? 如果在編譯源代碼模塊時(shí)沒有定義 UNICODE ,調(diào)用 LoadString 實(shí)際上就是調(diào)用 LoadStringA 函數(shù)。這時(shí) LoadStringA 就從你的資源中讀。
?
如何判斷一段文本是否 unicode ?
答: 通過IsTextUnicode 可以來判斷一段文本是否為unicode 文本,它采用的是統(tǒng)計(jì)和定性的方法來判斷,因此有時(shí)會(huì)不準(zhǔn)。
?
如何遍歷和操作 DBCS 字符串 ?
答: 在 crt 中,如_mbslen, 它可以用來操作多字節(jié)(既包括單字節(jié)也包括雙字節(jié))字符串。
???????????????????? 對DBCS 字符串進(jìn)行操作的幫助函數(shù)
| 函數(shù) | 描述 |
| PTSTR CharNext(PCTSTR pszCurrentChar); | 返回字符串中的下一個(gè)字符的地址 |
| PTSTR CharPrev(PCTSTR pszStart,PCTSTR pszCurrentChar); | 返回字符串中的上一個(gè)字符的地址 |
| BOOL IsDBCSLeadByteTRUE(BYTE bTestChar); | 如果該字節(jié)是DBCS 字符的第一個(gè)字節(jié),則返回 |
如果是unicode 字符串,則只要移動(dòng)指針就可以實(shí)現(xiàn)對字符串的遍歷。
?
常見的字符串類型有哪些 ?
答: 常見數(shù)據(jù)類型定義
| 數(shù)據(jù)類型 | 等價(jià)于 |
| LPTSTR | TCHAR * |
| LPCTSTR | const TCHAR * |
| wchar_t | unsigned short |
| WCHAR | wchar_t |
| LPWSTR | wchar_t * |
| LPCWSTR | const wchar_t * |
| LPSTR | char * |
| LPCSTR | const char * |
| OLECHAR | wchar_t |
| LPOLESTR | wchar_t * |
| LPCOLESTR | const wchar_t * |
?
_T(x) 、 __T(x) 、 _TEXT(x) 和 TEXT(x) 作用是什么?有什么區(qū)別?
答: _T(x) 、__T(x) 、_TEXT(x) 和TEXT(x) 作用相同,都是根據(jù)是否定義_UNICODE 宏來決定當(dāng)前字符或字符串x 轉(zhuǎn)換成寬字符串。
如果x 本身就是寬字符串則不做處理。
如果未定義_UNICODE ,則也對x 不做處理。
推薦使用TEXT(x) ,可讀性較好,也不用寫下劃線。
?
L 與 _T(x) 、 __T(x) 、 _TEXT(x) 、 TEXT(x) 有什么區(qū)別?
答:L 是明確告訴編譯器必須按照寬字符來處理。
??? 其他幾個(gè)是條件編譯的,由是否定義 UNICODE 宏決定。
?
如何操作 unicode 字符串?
答: 對Unicode 字符串進(jìn)行操作的函數(shù)
| 函數(shù) | 描述 |
| lstrcat | 將一個(gè)字符串置于另一個(gè)字符串的結(jié)尾處 |
| lstrcmp | 對兩個(gè)字符串進(jìn)行區(qū)分大小寫的比較 |
| lstrcmpi | 對兩個(gè)字符串進(jìn)行不區(qū)分大小寫的比較 |
| lstrcpy | 將一個(gè)字符串拷貝到內(nèi)存中的另一個(gè)位置 |
| lstrlen | 返回字符串的長度(按字符數(shù)來計(jì)量) |
??? 這些函數(shù)是作為宏來實(shí)現(xiàn)的,這些宏既可以調(diào)用函數(shù)的Unicode 版本,也可以調(diào)用函數(shù)的ANSI 版本,這要根據(jù)編譯源代碼模塊時(shí)是否已經(jīng)定義了UNICODE 而定。例如,如果沒有定義UNICODE ,lstrcat 函數(shù)將擴(kuò)展為lstrcatA 。如果定義了UNICODE ,lstrcat 將擴(kuò)展為lstrcatW 。
?
如何讓 printf 支持 ansi/unicode ?
答:讓_printf 接口來替換printf 即可。
??? 示例代碼:
??? TCHAR lpBuffer[_MAX_FNAME];
??? _tprintf(TEXT(“%s/n”),lpBuffer);
?
在字符串操作函數(shù)中如何處理 ansi 和 unicode 字符串?
答: 如果在定義了_ UNICODE 的情況下編譯你的源代碼模塊,那么printf 函數(shù)家族便希望所有字符和字符串參數(shù)代表Unicode 字符和字符串。但是,如果在沒有定義_UNICODE 的情況下編譯你的源代碼模塊,printf 函數(shù)家族便希望傳遞給它的所有字符和字符串都是ANSI 字符和字符串。
char szA[100];???????????? //An ANSI string buffer
WCHAR szW[100];??????????? //A Unicode string buffer
?
//Normal sprintf:all strings are ANSI
sprintf(szA, "%s","ANSI Str");
?
//Converts Unicode string to ANSI
sprintf(szA,"%S",L"Unicode Str");
?
//Normal swprintf:all strings are Unicode
swprintf(szW,L"%s",L"Unicode Str");
?
//Converts ANSI string to Unicode
swprintf(szW,L"%S", "ANSI Str");
?
在 vc6 中為什么編譯 MFC unicode 程序會(huì)出錯(cuò),如何處理?
答: 在vc6 缺省安裝的MFC 不支持unicode ,必須在安裝時(shí)選擇支持多語言或全部安裝。否則,會(huì)出現(xiàn)LINK : fatal error LNK1104: cannot open file "mfc42ud.lib" 的錯(cuò)誤。
?
什么情況下要用到資源 DLL ?
答:如果要想使UI 與邏輯分離,則制作資源DLL 是比較好的方法。
??? 好處有:
1、 ? UI 可以獨(dú)立于邏輯,獨(dú)立更新和升級。
2、 ? 如果要開發(fā)多語言應(yīng)用程序,不同語言的UI 只需要不同的資源DLL 即可,邏輯部分代碼不需要做任何改動(dòng)。
?
如何制作 win32 資源 DLL ?
答: 因?yàn)?span lang="EN-US">win32 程序中代碼和資源沒有直接的聯(lián)系,因此可以先設(shè)計(jì)UI 及其他資源并生成DLL ,然后在exe 程序中動(dòng)態(tài)加載資源DLL 。
?
??? 實(shí)現(xiàn)步驟 (以vc6 為例,一個(gè)簡單的文本編輯器示例):
1、 ? 創(chuàng)建一個(gè)win32 DLL 的工程,工程名稱為“NotePadRes ”,選擇“a simple DLL project ”,點(diǎn)擊finish 。
2、 ? 創(chuàng)建一個(gè)空的資源腳本文件,如MyNotePad.rc ,然后在ResourceView 中就會(huì)出現(xiàn)“MyNotePad resources ”目錄。
3、 ? 在ResourceView 中的“MyNotePad resources ”目錄上右鍵插入資源,設(shè)置資源ID 并編輯資源。在本示例中,我插入了圖標(biāo)、菜單和快捷鍵資源,你也可以插入其他資源(如位圖、字符串表、對話框、鼠標(biāo)等)。
??? 注意:在你編輯資源時(shí),vc 編譯器會(huì)自動(dòng)修改rc 文件,并且生成resource.h 文件。
4、 ? 編輯好資源后,編譯DLL ,輸出NotePadRes.dll 。
5、 ? 創(chuàng)建一個(gè)win32 application 的工程,工程名稱為“MyNotePad ”,選擇“a simple win32 application ”,點(diǎn)擊“完成”。
6、 ? 為了使用資源DLL 中的UI 資源,我們必須在創(chuàng)建窗口之前加載資源DLL ,因此在WinMain 的最開始處使用LoadLibrary 動(dòng)態(tài)加載NotePadRes.dll 。
7、 ? 使用加載DLL 作為參數(shù),加載菜單、快捷鍵和圖標(biāo)。注意:在注冊窗口類別時(shí)把菜單名稱設(shè)置為NULL ,而在創(chuàng)建窗口時(shí)把加載好的菜單句柄傳進(jìn)去。這是windows 創(chuàng)建個(gè)性化菜單的一種手段,讓相同類別的窗口可以有不同的菜單。
8、 ? 拷貝NotePadRes 項(xiàng)目生成的resource.h 到MyNotePad 的代碼目錄,并且在MyNotePad.cpp 中引用該頭文件,這樣就可以使用NotePadRes 中的資源ID 。
9、 ? 在MyNotePad.cpp 中實(shí)現(xiàn)菜單和快捷鍵的響應(yīng)代碼,我這里只是為了演示如何分離代碼和資源,因此很多菜單的響應(yīng)代碼都沒有實(shí)現(xiàn)。
10、 ????????????? 編譯MyNotePad 。
11、 ????????????? 拷貝NotePadRes.dll 到MyNotePad 項(xiàng)目的輸出目錄。
12、 ????????????? 執(zhí)行MyNotePad.exe ,觀察演示效果。
?
?
如何制作 MFC 資源 DLL ?
答: MFC 程序是通過clw 文件來建立資源與代碼的聯(lián)系,clw 文件是在設(shè)計(jì)資源框架并通過ClassWizard 添加接口時(shí)產(chǎn)生,由vc 編譯器維護(hù),手工編寫比較麻煩。
??? 另外,ClassWizad 不允許項(xiàng)目不包含資源文件。
??? 因?yàn)?span lang="EN-US">mfc 的代碼和資源關(guān)系比較密切,因此分離起來比win32 麻煩。
??? 一般MFC 程序資源和代碼分離的方法分為以下幾大步:1 、建立原型程序,完成所有UI 設(shè)計(jì)及相應(yīng)的接口框架。2 、編譯原型程序,并把rc 文件從原型中移出。3 、根據(jù)原型的rc 和resource.h 文件構(gòu)建資源DLL ,并在此基礎(chǔ)上進(jìn)行修改。4 、在原型中載入資源DLL 。
?
實(shí)現(xiàn)步驟 (以vc6 為例,一個(gè)單文檔文本編輯器示例):
1 、創(chuàng)建一個(gè)MFC AppWizard(exe) 工程,工程名稱為“MyNotePad ”,選擇“Simple Document ”,語言選擇中文,點(diǎn)擊finish 。
2 、為了實(shí)現(xiàn)動(dòng)態(tài)加載資源,則必須使用資源DLL 的句柄來取代MFC 缺省的資源句柄,MFC 缺省的資源是編譯在exe 中的。在CMyNotePadApp 中添加保護(hù)或私有變量m_hLangDLL 來保存資源DLL 句柄,在InitInstance 中加載資源DLL 并替換MFC 缺省資源句柄,在ExitInstance 中釋放資源DLL 。
注意: InitInstance 和ExitInstance 都是虛函數(shù),但是ExitInstance 在子類中沒有實(shí)現(xiàn),需要在CMyNotePadApp 定義虛函數(shù)并實(shí)現(xiàn)。
3 、為了說明是從資源鏈接庫中動(dòng)態(tài)地獲取數(shù)據(jù)而不是從程序的執(zhí)行體中獲取,該程序從資源鏈接庫中獲取了一個(gè)圖標(biāo)和一個(gè)字符串,并繪制在文檔顯示區(qū)域。代碼在CMyNotePadView::OnDraw 中實(shí)現(xiàn)。
??? 字符串ID 為IDS_WELCOME=300 ,內(nèi)容為”hello world” ,我們在后面的資源DLL 中改為其他內(nèi)容,以證實(shí)是從資源DLL 中加載的。
??? 圖標(biāo)也在資源DLL 中做修改,比如在圖標(biāo)中添加一個(gè)紅色的“中”字,以示區(qū)別于原來的圖標(biāo)。
4 、編譯運(yùn)行MyNotePad 工程。由于資源DLL 還未創(chuàng)建,運(yùn)行時(shí)會(huì)出現(xiàn)" 無法裝載資源鏈接庫!" 錯(cuò)誤提示。
5 、從MyNotePad 工程移出MyNotePad.rc 文件,并不從硬盤上刪除,因?yàn)楹竺鏄?gòu)建資源DLL 時(shí)要以此資源描述文件為基礎(chǔ)。
6 、創(chuàng)建一個(gè)MFC AppWizard(DLL) 的工程,工程名稱為“NotePadRes ”,選擇“Regular DLL using shared MFC DLL ”,點(diǎn)擊finish 。
7 、把NotePadRes.rc 和resource.h 從NotePadRes 工程中移出,并且從硬盤上刪除NotePadRes.rc 、resource.h 以及res 目錄下的所有文件。
8 、從MyNotePad 工程目錄中拷貝MyNotePad.rc 和resource.h 到NotePadRes 工程目錄下,并且把MyNotePad 工程的res 目錄下所有文件都拷貝到NotePadRes 工程的res 目錄下。
9 、把MyNotePad.rc 重命名為NotePadRes.rc 。根據(jù)個(gè)人喜好,此步可以不做,不影響正確性。
10 、在NotePadRes 工程中添加剛才拷貝的所有文件。
11 、修改字符串和圖標(biāo)。
12 、在工程的setting->Resources 的預(yù)處理中刪除_AFXDLL ,使用戶的鏈接庫包含通用的MFC 資源。否則,應(yīng)用程序會(huì)從系統(tǒng)安裝的MFC 動(dòng)態(tài)鏈接庫中收集通用的MFC 資源,應(yīng)用程序特定資源會(huì)被本地化。
13 、如果是制作其他語言版本的資源DLL ,還需要在setting->Resources 把語言改一下。
14 、在setting->link 的編譯選項(xiàng)中添加“/NOENTRY ”選項(xiàng),表示輸出的為純資源DLL 。
15 、編譯NotePadRes ,設(shè)置輸出chinese.dll 資源DLL 。
16 、拷貝chinese.dll 到MyNotePad 的輸出目錄。
17 、運(yùn)行MyNotePad.exe ,觀察演示效果。
?
兩種非 unicode 字符集如何轉(zhuǎn)換?
答: 兩種非unicode 字符集轉(zhuǎn)換方法,先把其中一種字符集轉(zhuǎn)換為unicode ,然后把unicode 字符集轉(zhuǎn)換為另外一種字符集。比如gb2312 與utf-8 轉(zhuǎn)換,先把gb2312 轉(zhuǎn)換為unicode ,然后把unicode 轉(zhuǎn)換為utf-8 。
?
如何轉(zhuǎn)換轉(zhuǎn)換 gb2312/gbk 為 unicode ?
答: int GbkTowchar(LPCSTR lpMultiByteStr,LPWSTR & lpWideCharStr,int & cchWideChar)
{
?? //revert utf8 string to wchar string
??? cchWideChar = ???????? ? MultiByteToWideChar(CP_ACP,0,lpMultiByteStr,strlen(lpMultiByteStr),NULL,0);
??? lpWideCharStr = new WCHAR[cchWideChar + 1];
?? memset(lpWideCharStr,0,sizeof(WCHAR) * (cchWideChar + 1));
?? MultiByteToWideChar(CP_ACP,0,lpMultiByteStr,strlen(lpMultiByteStr),lpWideCharStr,cchWideChar);
??
?? return cchWideChar;
}
?
// 使用轉(zhuǎn)換后pwStr 寬字符串
delete []lpWideCharStr;// 釋放寬字符串內(nèi)存
?
如何轉(zhuǎn)換轉(zhuǎn)換 unicode 為 utf-8 ?
答: int wcharToUTF8(LPCWSTR lpWideCharStr,LPSTR & lpMultiByteStr,int & cchMultiByte)
{
??? //revert wchar string to utf8 string
??? cchMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, sizeof(WCHAR) * wcslen(lpWideCharStr), lpMultiByteStr,0,NULL,NULL);// 獲取轉(zhuǎn)換成多字節(jié)字符串所需要的內(nèi)存
??? lpMultiByteStr = new char[cchMultiByte + 1];
??? memset(lpMultiByteStr,0,cchMultiByte + 1);
??? WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, sizeof(WCHAR) * wcslen(lpWideCharStr), lpMultiByteStr,cchMultiByte,NULL,NULL);
???
??? return cchMultiByte;
}
??? // 使用轉(zhuǎn)換后的字符串
??? Delete []lpMultiByteStr;// 釋放多字節(jié)字符串內(nèi)存
?
MySQL 字符集類型有哪些?
答: 類型:主機(jī)字符集、數(shù)據(jù)庫字符集、表字符集、列字符集、連接字符集。
關(guān)系:主機(jī)字符集 > 數(shù)據(jù)庫字符集 > 表字符集 > 列字符集,當(dāng)下一級字符集未指定時(shí),以上級字符集為準(zhǔn)。
?
?
MySQL 的各種字符集轉(zhuǎn)換關(guān)系是什么?
答:1 、發(fā)送請求。
??? 1) 客戶端發(fā)送請求到服務(wù)器端。
?? 2) 服務(wù)器端會(huì)把請求的數(shù)據(jù)從客戶端字符集(character_set_client) 轉(zhuǎn)成服務(wù)器連接字符集(character_set_connection) 。
?? 3) 然后服務(wù)器會(huì)檢測存儲區(qū)域(table ,column) 的字符集,然后把數(shù)據(jù)從連接字符集(character_set_connection) 轉(zhuǎn)為存儲區(qū)域(table ,column) 的字符集,然後再存儲或者查詢。
2 、返回請求。
? 1) 服務(wù)器將存儲區(qū)域(table ,column) 的字符集轉(zhuǎn)換成服務(wù)器連接字符集(character_set_connection) 。
? 2) 將服務(wù)器連接字符集(character_set_connection) 轉(zhuǎn)換成結(jié)果字符集(character_set_results) ,再發(fā)送到客戶端。
?
MySQL 字符集 Uincode 支持情況如何?
答: 1 、服務(wù)器端支持 UCS-2 Unicode ( UTF-16 )和 UTF-8 。
?????? 2 、客戶端只支持 UTF-8 。
?? ? 3 、在 4.1 之前的客戶端不支持 UTF-8 。
?
如何設(shè)置 MySQL 連接字符集?
答:有兩種方法:
1、 ? 在建立MySQL 連接前,設(shè)置MySQL 連接句柄屬性:
??? mysql_options(m_mysql_handle, MYSQL_SET_CHARSET_NAME, charset);
2、 ? 建立好MySQL 連接,在執(zhí)行所有SQL 語句前:
??? set names ‘ 字符集’;
?
國際化開發(fā)的協(xié)議字符串最好采用什么字符集?
答:最好使用UTF-8 ,原因是UTF-8 比較適合網(wǎng)絡(luò)傳輸,而且很方便的與其他字符集進(jìn)行轉(zhuǎn)換。
?
國際化開發(fā)的數(shù)據(jù)庫最好采用什么字符集?
答:數(shù)據(jù)庫的字符集最好采用UTF-8 ,理由同上。
??? 另外,數(shù)據(jù)庫遷移時(shí)比較方便,不用考慮字符集轉(zhuǎn)換的問題,不會(huì)產(chǎn)生亂碼。
?
為什么 MySQL 數(shù)據(jù)庫已經(jīng)使用了 UTF-8 ,但是查詢出來的結(jié)果還是亂碼?
答:數(shù)據(jù)庫連接字符集和寫數(shù)據(jù)庫的字符集必須相同,否則就會(huì)出現(xiàn)無法轉(zhuǎn)換的問題,這是亂碼的根源。具體如何轉(zhuǎn)換,前面有專門說明。
?
國際化開發(fā)的日志文件和配置文件采用什么字符集比較好?
答:建議采用帶BOM 的UTF-8 編碼。
??? 理由如下:
1、 ? 可以支持多種語言。
2、 ? 沒有字節(jié)序的問題,unicode 有字節(jié)序的問題,需要另外處理。
3、 ? 大多數(shù)文本或配置文件解析工具都支持utf-8 。
?
Linux 服務(wù)器國際化開發(fā)采用什么方案比較好?
答:
方案一:
??? 1 、日志和配置文件都采用utf-8 存儲(帶BOM )。
2 、網(wǎng)絡(luò)協(xié)議字符串采用utf-8 字符集。
3、 ? 讀寫數(shù)據(jù)庫采用utf-8 字符集。
4、 ? 如果需要對字符串進(jìn)行遍歷或修改,則把它轉(zhuǎn)換成unicode 處理,處理完成后再轉(zhuǎn)換成utf-8 。
5 、
此方案的好處是不用考慮字節(jié)序問題,缺點(diǎn)是對字符串進(jìn)行處理不太方便,要做轉(zhuǎn)換。
?
方案二:
??? 所有的文件和網(wǎng)絡(luò)I/O 及數(shù)據(jù)庫都采用unicode ,文件存儲帶BOM ,不過網(wǎng)絡(luò)協(xié)議中的字符串要指明字節(jié)序(或都轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序),這是它的不足之處。
??? 此方案的好處是所有字符串都可以直接處理,不用轉(zhuǎn)換。
??? 缺點(diǎn)是網(wǎng)絡(luò)協(xié)議中要指明字節(jié)序或轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序。
?
?
記事本中如何輸入并顯示韓文?
答:打開控制面板-區(qū)域和語言選項(xiàng)-語言-詳細(xì)信息-添加-輸入語言選朝鮮語-確定。這個(gè)步驟就是讓你有了系統(tǒng)自帶的韓文輸入法,你按 alt+shift 或者 ctrl+shift 就可以把這個(gè)韓文輸入法調(diào)出來了。
然后,打開記事本-格式-字體,接著,字體( F) 那里選 BatangChe ,字符集那里選“韓文”,確定。好了你現(xiàn)在可以調(diào)出你的韓文輸入法在記事本上輸韓文了。但是當(dāng)你想保存的時(shí)候就有個(gè)提醒,如果你點(diǎn)“是”,保存了,再次打開的時(shí)候,那些韓文會(huì)亂碼。如果點(diǎn)“否”,就不能保存。那有沒有什么方法保存呢,請看第三步。
第三步,點(diǎn)記事本的文件-另存為,在編碼那里選 Unicode 或 utf-8 ,保存。現(xiàn)在你打開另存為的那個(gè)記事本,韓文沒變亂碼。成功了,你甚至可以把文件名都改為韓文呢。
?
?
如何處理中文、泰文和阿拉伯文的字符消息?
答:由于中文字符編碼一般都是gb2312 或GBK ,由一個(gè)或兩個(gè)輸入字符組成,但是只顯示一個(gè)字符。
??? 泰文和阿拉伯文都每輸入一個(gè)字符就顯示一個(gè)字符。
??? 處理辦法:
1、 ? 中文版本中,收到字符后判斷最高位是否為1 ,即是否大于127 ,證明是有兩個(gè)字符組成的漢字。否則,就是ASCII 碼字母或數(shù)字。
2、 ? 泰文或阿拉伯文版本,每收到一個(gè)wm_char 消息就顯示到屏幕上。
?
如何處理多語言界面字體顯示亂碼?
答:盡管把字符串變成了unicode ,但是有時(shí)仍然是顯示亂碼,原因是字體設(shè)置不正確。比如讓中文字體顯示泰文,或者反之,都不可能正常顯示的。
處理方法有兩種:
1、 ? 設(shè)置一種比較通用的字體,比如Arial Unicode MS ,此種方法一般用在支持換語言皮膚的應(yīng)用程序中。
2、 ? 根據(jù)不同語言設(shè)置不同的典型字體,比如對于簡體中文,設(shè)置仿宋體等肯定能夠正常顯示。
3 、方法一的字體不是非常美觀,而且對于沒有編入unicode 的字符無法顯示。
?
總結(jié)
以上是生活随笔為你收集整理的国际化开发技术FAQ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux查看端口占用情况的命令
- 下一篇: 算命先生有三不算:不算死人、不算同行、不