vc 国际化的资源文件处理
MS Windows操作系統(tǒng)是一個(gè)世界上廣泛使用的操作系統(tǒng),對(duì)于不同語種的國(guó)家MS Windows有相應(yīng)語種的版本。在不同語種的Windows平臺(tái)上應(yīng)該運(yùn)行相應(yīng)語種的應(yīng)用程序。也就是說程序的用戶界面(如菜單、對(duì)話框、狀態(tài)條)中的提示文字應(yīng)該使用和Windows操作系統(tǒng)所使用的語種一致。當(dāng)然英語用戶界面的程序可以運(yùn)行在其它語言平臺(tái)上,但比較復(fù)雜的程序或多或少都有問題,如對(duì)話框的尺寸不對(duì),特殊的ASCII字符顯示為文字,輸入字符串可能會(huì)導(dǎo)致死機(jī)等。如果不一致卻還想使用,則需要?jiǎng)討B(tài)翻譯軟件。例如,在英文Windows平臺(tái)上運(yùn)行中文版的MS Office就需要像中文之星或四通利方這樣的中文動(dòng)態(tài)翻譯軟件。
當(dāng)前國(guó)內(nèi)使用的MS Windows在語種上劃分主要有簡(jiǎn)體中文版和英文版兩種。為了讓開發(fā)的軟件能在這兩種平臺(tái)上使用,提出了三種解決方案:第一種解決方案是僅編寫中文界面的程序。在中文Windows上程序可以運(yùn)行(這里的運(yùn)行是指程序界面不出現(xiàn)亂碼),在英文Windows上依靠中文之星或四通利方這樣的中文動(dòng)態(tài)翻譯軟件也可以運(yùn)行。第二種解決方案是針對(duì)中文版和英文版各編一個(gè)程序,即在第一種方案的基礎(chǔ)上增加了英文版,這樣做有兩點(diǎn)好處:一是英文Windows平臺(tái)上運(yùn)行英文版的軟件比英文Windows平臺(tái)上運(yùn)行中文版的軟件穩(wěn)定,因?yàn)闆]有像中文之星或四通利方這樣的中文動(dòng)態(tài)翻譯軟件的參與。第三種解決方案是自動(dòng)根據(jù)操作系統(tǒng)的語種選擇相應(yīng)的界面語種。也就是說,同一個(gè)軟件在中文Windows上顯示中文界面,在英文Windows上顯示英文界面。這種方案相對(duì)于第二種方案的好處在于:程序不用做英文版和中文版兩個(gè)版本,只要一個(gè)版本就可以了,對(duì)于用戶來說是很方便的。在這三種方案中,前一種是后一種的基礎(chǔ),后一種實(shí)現(xiàn)了,前一種也就已經(jīng)實(shí)現(xiàn)了。下面將從易到難介紹三種方案實(shí)現(xiàn)的步驟和要點(diǎn)。
解決方案一、自動(dòng)生成中文界面框架
Visual C++6.0版本中可以使用APPWIZARD自動(dòng)生成具有基本中文界面的WIN32應(yīng)用程序。使用APPWIZARD時(shí),在自動(dòng)生成的第一個(gè)步驟中,將資源類型選擇為簡(jiǎn)體中文就可以了,可參見圖1。其余選項(xiàng)都不涉及語種問題,根據(jù)應(yīng)用程序的具體情況進(jìn)行選擇即可。然后在此基礎(chǔ)上作進(jìn)一步的軟件開發(fā)工作。
如果你在一邊讀文章一邊上機(jī)實(shí)際操作,可能會(huì)發(fā)現(xiàn)一個(gè)問題:不論你怎樣設(shè)定VisualC++5.0的安裝程序的選項(xiàng),資源類型僅會(huì)支持英語、德語、法語、西班牙語和意大利語這五種語言。于是你可能會(huì)懷疑你所用的Visual C++5.0版本有問題。實(shí)際上并不是Visual C++5.0版本有問題,而是需要從安裝盤上手工拷貝一些文件。所需文件在Visual Studio97軟件包的第三張包含Visual C++5.0的光盤上。在目錄DEVSTUDIO/SHAREDIDE/BIN/IDE下有幾個(gè)以APPWZ開頭的動(dòng)態(tài)鏈接庫(擴(kuò)展名為dll的文件)。在這些動(dòng)態(tài)鏈接庫中,一個(gè)動(dòng)態(tài)鏈接庫提供對(duì)一種語言的支持。其中的APPWZCHS.DLL就是支持簡(jiǎn)體中文的文件。將其拷貝到安裝Visual C++5.0的硬盤上相同名字的目錄下即可。重新開始自動(dòng)生成步驟,在自動(dòng)生成的第一個(gè)步驟中,在資源類型選擇中將出現(xiàn)簡(jiǎn)體中文支持。
解決方案二、支持多種語言
沒有必要從頭開發(fā)一個(gè)英文版。事實(shí)上,在現(xiàn)有中文版的基礎(chǔ)上生成英文版并不復(fù)雜。工作量在于修改資源,程序的代碼不用改變。
圖2左邊的ResourceView窗口中,同時(shí)存在著中英文兩種資源,在中文資源的后面標(biāo)注有“Chinese(P.R.C.)”以示區(qū)別。為了保證程序代碼不變,相同界面元素的兩種語言版本下的標(biāo)識(shí)符必須相同。例如,產(chǎn)品介紹對(duì)話框的英文資源的標(biāo)識(shí)符為IDD_ABOUTBOX,中文資源的標(biāo)識(shí)符也應(yīng)該是IDD_ABOUTBOX。可以用COPY操作對(duì)資源進(jìn)行復(fù)制,然后修改語種再修改標(biāo)識(shí)符。 (在資源中用InsertCopy COPY一份資源)
ResourceView提供的管理功能并不全面,還需要直接編輯資源文件RESOURCE.RC來完成全部任務(wù)。經(jīng)過對(duì)RESOURCE.RC文件的研究,發(fā)現(xiàn)文件中使用編譯控制開關(guān)來實(shí)現(xiàn)多語言支持。 ......
//
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
//
// Dialog
......
/
// Menu
......
//
// Icon
......
//
// Bitmap
......
//
// Toolbar
......
#ifdef APSTUDIO_INVOKED
/
// TEXTINCLUDE
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h/0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""/r/n"
"/0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES/r/n"
"#define _AFX_NO_PROPERTY_RESOURCES/r/n"
"/r/n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)/r/n"
"#ifdef _WIN32/r/n"
"LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED/r/n"
"#pragma code_page(936)/r/n"
"#endif/r/n"
"#include ""res//sample.rc2"" // non-Microsoft Visual C++ edited resources/r/n"
"#include ""l.chs//afxres.rc"" // Standard components/r/n"
"#include ""l.chs//afxprint.rc"" // printing/print preview resources/r/n"
"#include ""l.chs//afxolecl.rc"" // OLE container resources/r/n"
"#include ""l.chs//afxolesv.rc"" // OLE server resources/r/n"
"#endif/0"
END
#endif // APSTUDIO_INVOKED
......
#endif // Chinese (P.R.C.) resources
/
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
//
// Dialog
......
/
// Menu
......
//
// Icon
......
//
// Bitmap
......
//
// Toolbar
......
/
// TEXTINCLUDE
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h/0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""/r/n"
"/0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES/r/n"
"#define _AFX_NO_PROPERTY_RESOURCES/r/n"
"/r/n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)/r/n"
"#ifdef _WIN32/r/n"
"LANGUAGE 9, 1/r/n"
"#pragma code_page(1252)/r/n"
"#endif/r/n"
"#include ""res//sample.rc2"" // non-Microsoft Visual C++ edited resources/r/n"
"#include ""afxres.rc"" // Standard components/r/n"
"#include ""afxprint.rc"" // printing/print preview resources/r/n"
"#include ""afxolecl.rc"" // OLE container resources/r/n"
"#include ""afxolesv.rc"" // OLE server resources/r/n"
"#endif/0"
END
#endif // APSTUDIO_INVOKED
......
#endif // English (U.S.) resources
/
#ifndef APSTUDIO_INVOKED
/
// Generated from the TEXTINCLUDE 3 resource.
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif
#include "res/sample.rc2" // non-Microsoft Visual C++ edited resources
#include "l.chs/afxres.rc" // Standard components
#include "l.chs/afxprint.rc" // printing/print preview resources
#include "l.chs/afxolecl.rc" // OLE container resources
#include "l.chs/afxolesv.rc" // OLE server resources
#endif
?
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif
#include "res/sample.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#include "afxprint.rc" // printing/print preview resources
#include "afxolecl.rc" // OLE container resources
#include "afxolesv.rc" // OLE server resources
#endif
/
#endif // not APSTUDIO_INVOKED
以上代碼中在 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)宏定義后面為中文資源,在#if !defined(AFX_RESOURCE_DLL)|| defined(AFX_TARG_ENU)宏定義后面為英文資源。應(yīng)該保證中英文資源中都有TEXTINCLUDE段和#ifndef APSTUDIO_INVOKED段。?這樣MFC(Microsoft Fundermental Class)缺省資源才會(huì)被包含。 對(duì)于中文資源來講,這些額外資源的路徑應(yīng)加上l.chs目錄名。
在編譯生成可執(zhí)行文件時(shí),如果生成中文版本,則在Project Settings對(duì)話框中應(yīng)按圖3所示進(jìn)行設(shè)置:在Preprocessor definitions編輯框中加入AFX_TARG_CHS和AFX_RESOURCE_DLL的定義,并且Language選擇框中應(yīng)選擇Chinese(P.R.C.)。如果生成英文版本,則在Project Settings對(duì)話框中應(yīng)設(shè)置如下:在Preprocessor definitions編輯框中加入AFX_TARG_ENU和AFX_RESOURCE_DLL的定義,并且Language選擇框中應(yīng)選擇English(United States)。
其中AFX_TARG_CHS與936定義了資源文件的簡(jiǎn)體中文屬性。
英文屬性中為AFX_TARG_ENU與1252,
日文屬性中為AFX_TARG_JPN與932,
繁體中文屬性中為AFX_TARG_CHT與950。
翻譯時(shí)必須改成相應(yīng)的語言屬性。
注意下面兩句也應(yīng)改動(dòng):
#include "l.chs//afxres.rc" // Standard components
#include "l.chs//afxprint.rc" // printing/print preview resources
英文為:
#include "afxres.rc" // Standard components
#include "afxprint.rc" // printing/print preview resources
日文為:
#include "l.jpn//afxres.rc" // Standard components
#include "l.jpn//afxprint.rc" // printing/print preview resources
繁體中文為:
#include "l.cht//afxres.rc" // Standard components
#include "l.cht//afxprint.rc" // printing/print preview resources
還有一點(diǎn)需要注意,就是所有在代碼中顯示的文字串都應(yīng)存儲(chǔ)在資源文件中,而不應(yīng)該在程序中使用硬編碼。例如,以下代碼就是硬編碼:
......
MessageBox(_T("文件沒有找到!"),_T("錯(cuò)誤")) ;
......
這種提示僅限于Windows簡(jiǎn)體中文版,而在沒有像中文之星、四通利方等翻譯軟件的Windows英文版平臺(tái)上顯示的將是一堆亂碼。正確的方法應(yīng)該是:
......
Cstring string1, string2 ;
string1.LoadString(IDS_FILE_NOT_FIND) ;
string2.LoadString(IDS_ERROR) ;
MessageBox(string1, string2) ;
......
在中文資源中,IDS_FILE_NOT_FIND對(duì)應(yīng)“文件沒有找到!”字符串,IDS_ERROR對(duì)應(yīng)“錯(cuò)誤”字符串;在英文資源中IDS_FILE_NOT_FIND對(duì)應(yīng)“File not found! ”字符串,IDS_ERROR對(duì)應(yīng)“Error”字符串。
三、不同語種平臺(tái)的自動(dòng)選擇
實(shí)現(xiàn)這項(xiàng)功能的思路是使用純資源DLL,把應(yīng)用程序中的資源都放在純資源DLL中。這種DLL僅含有資源而沒有可執(zhí)行代碼,也就是源文件中僅包含RC資源文件。應(yīng)用程序中中文和英文資源可放在不同的DLL中。例如,中文資源DLL名為CHINESE.DLL,它放置中文資源;英文資源DLL名為ENGLISH.DLL,它放置英文資源。程序啟動(dòng)時(shí)根據(jù)Windows平臺(tái)語種的類型,加載相應(yīng)的DLL。以后資源就會(huì)從對(duì)應(yīng)的DLL中讀取,從而能保證使用正確的資源.。
為了實(shí)現(xiàn)這項(xiàng)功能,需要在應(yīng)用程序類中加入一個(gè)變量以存儲(chǔ)資源DLL的句柄并重載應(yīng)用程序類中的InitInstance和ExitInstance函數(shù)。
在應(yīng)用程序類聲明中加入代碼如下:
......
protected:
HINSTANCE m_hLangDLL ;
......
在InitInstance函數(shù)開始處加入代碼如下:
// Get the primary language identifier
WORD wLangPID = PRIMARYLANGID(::GetSystemDefaultLangID()) ;
// Load the language resource DLL
switch( wLangPID )
{
case LANG_ENGLISH:
m_hLangDLL = ::LoadLibrary("english.dll") ;
break ;
case LANG_CHINESE:
m_hLangDLL = ::LoadLibrary("chinese.dll") ;
break ;
}
if( !m_hLangDLL)
{
AfxMessageBox(_T("Unable to load resource DLL!")) ;
return FALSE ;
}
// Tell the application what module contains our resource
AfxSetResourceHandle(m_hLangDLL) ;
......
在ExitInstance函數(shù)開始處加入代碼如下:
// Free language resource library
if(m_hLangDLL)
{
FreeLibrary(m_hLangDLL) ;
}
......
操作系統(tǒng)所使用的語言由WIN32函數(shù)GetSystemDefaultLangID取得。宏P(guān)RIMARYLANGID又取出主語言標(biāo)識(shí)符進(jìn)行判斷,選擇應(yīng)該調(diào)用的DLL。DLL的加載由WIN32函數(shù)LoadLibrary實(shí)現(xiàn)。程序中所使用的資源庫由AfxSetResourceHandle函數(shù)指定。程序退出時(shí)用WIN32函數(shù)FreeLibrary卸載。
還有,在編譯資源DLL時(shí)別忘了在連接時(shí)加上/NOENTRY選項(xiàng)以告訴連接器這是一個(gè)唯一資源的DLL,不包含程序執(zhí)行的入口點(diǎn)。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的vc 国际化的资源文件处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于考核与面谈
- 下一篇: MVC4建立DBContext的EF6数