vc 國際化的資源文件處理
MS Windows操作系統是一個世界上廣泛使用的操作系統,對于不同語種的國家MS Windows有相應語種的版本。在不同語種的Windows平臺上應該運行相應語種的應用程序。也就是說程序的用戶界面(如菜單、對話框、狀態條)中的提示文字應該使用和Windows操作系統所使用的語種一致。當然英語用戶界面的程序可以運行在其它語言平臺上,但比較復雜的程序或多或少都有問題,如對話框的尺寸不對,特殊的ASCII字符顯示為文字,輸入字符串可能會導致死機等。如果不一致卻還想使用,則需要動態翻譯軟件。例如,在英文Windows平臺上運行中文版的MS Office就需要像中文之星或四通利方這樣的中文動態翻譯軟件。
當前國內使用的MS Windows在語種上劃分主要有簡體中文版和英文版兩種。為了讓開發的軟件能在這兩種平臺上使用,提出了三種解決方案:第一種解決方案是僅編寫中文界面的程序。在中文Windows上程序可以運行(這里的運行是指程序界面不出現亂碼),在英文Windows上依靠中文之星或四通利方這樣的中文動態翻譯軟件也可以運行。第二種解決方案是針對中文版和英文版各編一個程序,即在第一種方案的基礎上增加了英文版,這樣做有兩點好處:一是英文Windows平臺上運行英文版的軟件比英文Windows平臺上運行中文版的軟件穩定,因為沒有像中文之星或四通利方這樣的中文動態翻譯軟件的參與。第三種解決方案是自動根據操作系統的語種選擇相應的界面語種。也就是說,同一個軟件在中文Windows上顯示中文界面,在英文Windows上顯示英文界面。這種方案相對于第二種方案的好處在于:程序不用做英文版和中文版兩個版本,只要一個版本就可以了,對于用戶來說是很方便的。在這三種方案中,前一種是后一種的基礎,后一種實現了,前一種也就已經實現了。下面將從易到難介紹三種方案實現的步驟和要點。
解決方案一、自動生成中文界面框架
Visual C++6.0版本中可以使用APPWIZARD自動生成具有基本中文界面的WIN32應用程序。使用APPWIZARD時,在自動生成的第一個步驟中,將資源類型選擇為簡體中文就可以了,可參見圖1。其余選項都不涉及語種問題,根據應用程序的具體情況進行選擇即可。然后在此基礎上作進一步的軟件開發工作。
如果你在一邊讀文章一邊上機實際操作,可能會發現一個問題:不論你怎樣設定VisualC++5.0的安裝程序的選項,資源類型僅會支持英語、德語、法語、西班牙語和意大利語這五種語言。于是你可能會懷疑你所用的Visual C++5.0版本有問題。實際上并不是Visual C++5.0版本有問題,而是需要從安裝盤上手工拷貝一些文件。所需文件在Visual Studio97軟件包的第三張包含Visual C++5.0的光盤上。在目錄DEVSTUDIO/SHAREDIDE/BIN/IDE下有幾個以APPWZ開頭的動態鏈接庫(擴展名為dll的文件)。在這些動態鏈接庫中,一個動態鏈接庫提供對一種語言的支持。其中的APPWZCHS.DLL就是支持簡體中文的文件。將其拷貝到安裝Visual C++5.0的硬盤上相同名字的目錄下即可。重新開始自動生成步驟,在自動生成的第一個步驟中,在資源類型選擇中將出現簡體中文支持。
解決方案二、支持多種語言
沒有必要從頭開發一個英文版。事實上,在現有中文版的基礎上生成英文版并不復雜。工作量在于修改資源,程序的代碼不用改變。
圖2左邊的ResourceView窗口中,同時存在著中英文兩種資源,在中文資源的后面標注有“Chinese(P.R.C.)”以示區別。為了保證程序代碼不變,相同界面元素的兩種語言版本下的標識符必須相同。例如,產品介紹對話框的英文資源的標識符為IDD_ABOUTBOX,中文資源的標識符也應該是IDD_ABOUTBOX。可以用COPY操作對資源進行復制,然后修改語種再修改標識符。 (在資源中用InsertCopy COPY一份資源)
ResourceView提供的管理功能并不全面,還需要直接編輯資源文件RESOURCE.RC來完成全部任務。經過對RESOURCE.RC文件的研究,發現文件中使用編譯控制開關來實現多語言支持。 ......
//////////////////////////////////////////////////////////////////////////
// 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)宏定義后面為英文資源。應該保證中英文資源中都有TEXTINCLUDE段和#ifndef APSTUDIO_INVOKED段。 這樣MFC(Microsoft Fundermental Class)缺省資源才會被包含。 對于中文資源來講,這些額外資源的路徑應加上l.chs目錄名。
在編譯生成可執行文件時,如果生成中文版本,則在Project Settings對話框中應按圖3所示進行設置:在Preprocessor definitions編輯框中加入AFX_TARG_CHS和AFX_RESOURCE_DLL的定義,并且Language選擇框中應選擇Chinese(P.R.C.)。如果生成英文版本,則在Project Settings對話框中應設置如下:在Preprocessor definitions編輯框中加入AFX_TARG_ENU和AFX_RESOURCE_DLL的定義,并且Language選擇框中應選擇English(United States)。
其中AFX_TARG_CHS與936定義了資源文件的簡體中文屬性。
英文屬性中為AFX_TARG_ENU與1252,
日文屬性中為AFX_TARG_JPN與932,
繁體中文屬性中為AFX_TARG_CHT與950。
翻譯時必須改成相應的語言屬性。
注意下面兩句也應改動:
#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
還有一點需要注意,就是所有在代碼中顯示的文字串都應存儲在資源文件中,而不應該在程序中使用硬編碼。例如,以下代碼就是硬編碼:
......
MessageBox(_T("文件沒有找到!"),_T("錯誤")) ;
......
這種提示僅限于Windows簡體中文版,而在沒有像中文之星、四通利方等翻譯軟件的Windows英文版平臺上顯示的將是一堆亂碼。正確的方法應該是:
......
Cstring string1, string2 ;
string1.LoadString(IDS_FILE_NOT_FIND) ;
string2.LoadString(IDS_ERROR) ;
MessageBox(string1, string2) ;
......
在中文資源中,IDS_FILE_NOT_FIND對應“文件沒有找到!”字符串,IDS_ERROR對應“錯誤”字符串;在英文資源中IDS_FILE_NOT_FIND對應“File not found! ”字符串,IDS_ERROR對應“Error”字符串。
三、不同語種平臺的自動選擇
實現這項功能的思路是使用純資源DLL,把應用程序中的資源都放在純資源DLL中。這種DLL僅含有資源而沒有可執行代碼,也就是源文件中僅包含RC資源文件。應用程序中中文和英文資源可放在不同的DLL中。例如,中文資源DLL名為CHINESE.DLL,它放置中文資源;英文資源DLL名為ENGLISH.DLL,它放置英文資源。程序啟動時根據Windows平臺語種的類型,加載相應的DLL。以后資源就會從對應的DLL中讀取,從而能保證使用正確的資源.。
為了實現這項功能,需要在應用程序類中加入一個變量以存儲資源DLL的句柄并重載應用程序類中的InitInstance和ExitInstance函數。
在應用程序類聲明中加入代碼如下:
......
protected:
HINSTANCE m_hLangDLL ;
......
在InitInstance函數開始處加入代碼如下:
// 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函數開始處加入代碼如下:
// Free language resource library
if(m_hLangDLL)
{
FreeLibrary(m_hLangDLL) ;
}
......
操作系統所使用的語言由WIN32函數GetSystemDefaultLangID取得。宏PRIMARYLANGID又取出主語言標識符進行判斷,選擇應該調用的DLL。DLL的加載由WIN32函數LoadLibrary實現。程序中所使用的資源庫由AfxSetResourceHandle函數指定。程序退出時用WIN32函數FreeLibrary卸載。
還有,在編譯資源DLL時別忘了在連接時加上/NOENTRY選項以告訴連接器這是一個唯一資源的DLL,不包含程序執行的入口點。
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成