用VC資源動態鏈接庫解決國際化問題

隨着計算機應用的普及,應用軟件跨國使用越來越頻繁,如何實現應用軟件的國際化,成爲許多程序員關心的問題。這種國際化問題相對使用某一種語言的用戶來說,就是本地化問題。本地化的含義比僅僅翻譯菜單欄和對話框的文本內容要廣泛得多,如特定文化背景的位圖和圖標對不同的人來說,可能會有不同的含義。在Windows系統中,應用程序開發者可以通過利用VC動態鏈接庫,只用一套源代碼就能簡潔地支持多種文字。本文介紹用VC的資源動態鏈接庫解決國際化問題的具體方法和步驟。

實現技術

利用VC編程,可以把所有的可見資源封裝在一個資源動態鏈接庫中,以簡化本地化工作。一般情況下,資源包含在應用程序中,但也可以通過調用AfxSetResourceHandle函數指向一個不同的單元以完成資源的引用。本文例程就是首先調用該函數從動態鏈接庫中採集到所有的應用程序可用資源,然後通過調用GetSystemDefaultLangID函數判斷系統默認語種,以載入不同語種的資源動態鏈接庫實現界面與系統的自動適應。
爲說明清楚,本文創建了一個默認語種爲簡體中文的Languages應用程序。該程序不含任何資源,應用程序根據系統的語種設置連接對應的資源鏈接庫,以完成對中文和英文兩種語言的支持。

實現步驟

1.創建Languages執行體

首先,用MFC AppWizad(exe)創建新項目的工作區,選擇Simple Document類型、中國中文(其他的選項選擇缺省),並且爲了明確,將工作區目錄改爲“多語種支持”。

2.添加數據成員

由於要動態地裝入資源鏈接庫,所以需要保存鏈接庫的句柄以便在程序結束的時候釋放資源。將下述數據成員添加到CLanguagesApp類中:
protected:
//資源鏈接庫句柄
HINSTANCE m_hLangDLL; 

3.修改InitInstance函數

應用程序需要判別系統的缺省語種,並裝入對應的資源鏈接庫。將下面的代碼加到InitInstance函數中:
BOOL CLanguagesApp::InitInstance()
{
 AfxEnableControlContainer();
 // 判定系統缺省語種
 WORDwLangPID=PRIMARYLANGID(::GetSystemDefaultLangID());
 // 載入資源動態鏈接庫
 switch(wLangPID )
 {
  caseLANG_CHINESE:
 m_hLangDLL=::LoadLibrary(“chinese.dll”);
    break ;
  default:
  m_hLangDLL=::LoadLibrary(“english.dll”);
break;
}
if( !m_hLangDLL)
{
 AfxMessageBox(_T(“無法裝載資源鏈接庫!”)) ;
  return FALSE;
}
// 連接資源
 AfxSetResourceHandle(m_hLangDLL);
……
}

其中,操作系統所使用的默認語種由Win 32函數GetSystemDefaultLangID取得。宏PRIMARYLANGID取出主語言標識符進行判斷,以正確選擇應該調用的鏈接庫。鏈接庫的加載由Win32函數LoadLibrary實現。程序中所使用的資源庫由AfxSetResourceHandle函數指定。

4.處理ExitInstance函數

程序退出時使用Win 32函數FreeLibrary卸載已經裝入的動態鏈接庫。將下列代碼添加到ExitInstance函數中:
int CLanguagesApp::ExitInstance()  
{
 // 釋放資源鏈接庫
 if(m_hLangDLL)  
  AfxFreeLibrary(m_hLangDLL);
 returnCWinApp::ExitInstance();
}

5.修改OnDraw

爲了說明是從資源鏈接庫中動態地獲取數據而不是從程序的執行體中獲取,該程序從資源鏈接庫中獲取了一個圖標和一個字符串,並繪製在屏幕上。下面是主要代碼:
void CLanguagesView::OnDraw(CDC* pDC)
{
CLanguagesDoc* pDoc =GetDocument();
ASSERT_VALID(pDoc);
//畫出從鏈接庫加載的圖標
pDC->DrawIcon(10,10,AfxGetApp()->LoadIcon(IDR_MAINFRAME));
//顯示字符串
CString strMsg;
strMsg.LoadString(IDS_HELLO);
pDC->TextOut(60,15,strMsg);
}

6.從項目中移走Languages.rc

由於本文項目自身並不需要含有任何資源,所以從項目列表文件中移走Languages.rc文件(並不刪除)。ClassWizad不允許項目不包含資源文件,所以可以創建一個空資源文件並加入到項目中,然後重建信息文件(Languages.CLW),使得ClassWizad可以繼續管理程序的消息處理。但在本例由於所有的函數都已經加入,可不必爲項目創建空資源文件。

7.建立項目

修改設置,從Project菜單選擇Setting…選項。在Link標籤下將輸出文件名由\Debug\Languages.exe改爲Languages.exe。編譯項目,由於應用程序中沒有任何資源,會出現找不到資源鏈接庫的錯誤,下面的一系列步驟爲本項目分別創建簡體中文和美國英語的資源鏈接庫。在這兩個鏈接庫建立後,把它們放到Languages項目目錄中,程序就可以運行了。
建立中文資源鏈接庫

1.創建新項目

爲了統一起見,將新創建的Language_chinese項目和Languages項目放在同一工作區內,並將項目目錄作爲工作區目錄“多語種支持”的子目錄。選擇Regular DLL-based應用程序並按下Finish鍵完成創建。動態鏈接庫項目只包含資源,不需要其他文件,所以從項目中刪除所有其他文件。

2.拷貝資源文件

把Languages相關的資源文件拷貝到Language_chinese項目的對應目錄下。表1是需要拷貝的文件名。
表1
文件名稱 註釋
Languages.rc 資源描述文件
Resource.h 包含資源定義的頭文件
Res\Languages.ico 主程序圖標
Res\Languages.rc2 用於定義資源的描述文件
Res\LanguagesDoc.ico 文檔圖標
Res\Toolbar.bmp 工具條位圖

3.將資源文件添加到項目中

把Languages.rc加入到Language_chinese項目中,使得項目中的唯一文件是Languages.rc。

4.修改資源

將ID_MAINFRAME的圖標改成代表簡體中文的圖標,該圖標將在Languages應用程序顯示窗口中出現。在串資源表中添加串IDS_HELLO=200,標題爲“嗨,這是中文版。”。

5.修改連接編譯設置

從Project菜單中選擇Setting…選項。首先,將輸出文件名由\Debug\Language_chinese.dll改爲..\chinese.dll,將動態鏈接庫直接建立在Languages項目目錄下。然後在鏈接命令行中添加“/NOENTRY”選項。最後,編譯並建立動態鏈接庫。
也可以建立一個初始化鏈接庫原文件,這樣就無需在鏈接命令行中添加“/NOENTRY”選項。程序主要代碼如下:
#include<windows.h>
extern “C”
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
return 1;
}

建立英文資源動態鏈接庫

生成英文版資源文件最快捷的方法是創建一個基於英文版的臨時項目,並把資源文件拷到英文鏈接庫項目中。其處理方法類似於中文資源鏈接庫。
需要注意的是:在修改資源組件設置時,不但要將Project菜單Setting對話框中Resource標籤的缺省文字改爲“英語(美國)”,還要刪除預處理定義中的“_AFXDLL”。刪除_AFXDLL預處理器,可以使用戶的鏈接庫包含通用的MFC資源。否則,應用程序會從系統安裝的MFC動態鏈接庫中收集通用的MFC資源,應用程序特定資源會被本地化。

小 結

Windows應用程序的資源一般捆綁在執行程序上,當需要時纔將其裝入。當需要某資源時,需要給Windows提供兩個參數:應用程序的實例句柄和資源的標識符。當某個鏈接庫裝入時,Windows返回一個實例句柄,可以通過該句柄引用鏈接庫中的資源。
需要注意的是:由於內存不夠或其他的一些資源問題,可能會導致加載資源失敗。

發佈了3 篇原創文章 · 獲贊 29 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章