1. 程式人生 > >在VC工程中新增多語言支援 (資源DLL)

在VC工程中新增多語言支援 (資源DLL)

隨著貿易國際化,在軟體開發過程中,常會碰到需在現有中文版軟體加入多語言支援的情況。由於不同語言版本間的差別通常僅是軟體操作介面的不同,為實現多語言支援,使用純資源DLL是一個不錯的解決之道。所謂純資源DLL是指只包含資源的DLL,譬如:快捷鍵、對話方塊、字串、選單、工具條、點陣圖、圖示、版本資訊等等。

具體做法是:利用VC視覺化編輯環境為每種語言製作一套資源ID一一對應的資源集並編譯生成DLL檔案。應用程式初始化時按預設的語言設定選擇合適的資源DLL調入,使用資源時依據資源ID進行訪問,這樣即可實現軟體的多語言支援。當然了,應用程式退出前,注意將動態調入的DLL檔案佔用的資源釋放。

現有一個心電圖檢視程式,工程名為DispECG,語言為中文,現需加入英文支援。下面根據這個具體例項來說明在VC中加入多語言支援的具體實施方法。

(一)建立純資源DLL

a)開啟DispECG工程,在當前工作區中新增一個工程。方法:使用選單File\New…

b)從彈出的對話方塊中選擇“Projects”頁面,選擇“Win32 Dynamic-Link Library”,工程名設定為“DispECG_ENG”,DispECG工程的工作目錄為D:\MyProject\DispECG,DispECG_ENG工程的工作目錄為D:\MyProject\DispECG\DispECG_ENG。選擇新增到當前工作區(注意Dependency of前的框不選),然後按OK。

c)建立一個簡單的DLL工程

選擇“A simple DLL project”,然後按“Finish”。此時新建的DispECG_ENG工程中會建立如下幾個檔案:DispECG_ENG.cpp,StdAfx.cpp,StdAfx.h以及ReadMe.txt。注意沒有後綴為*.RC的資原始檔。

其中DispECG_ENG.cpp中檔案內容如下:

        // DispECG_ENG.cpp : Defines the entry point for the DLL application.

        //

#include "stdafx.h"

BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call,

        LPVOID lpReserved)

        {

                return TRUE;

        }

(二)為DispECG_ENG加入資源並編輯

a)使用Windows資源管理器將DispECG工程下的resource.h和DispECG.rc拷貝到DispECG_ENG工程下,將DispECG工程下的res子目錄拷貝到DispECG工程下;

b)使用Windows資源管理器將DispECG_ENG工程下的DispECG.rc改名為DispECG_ENG.rc,將DispECG_ENG\res下的DispECG.rc2改名為DispECG_ENG.rc2;

c)回到VC編輯環境。選擇工作區中的檔案視(FileView),選擇“DispECG_ENG files”,單擊右鍵,選擇“Add Files to Project…”將DispECG_ENG工程下的resource.h和DispECG_ENG.rc加入到DispECG_ENG工程。

資原始檔DispECG_ENG.rc及資源ID定義檔案resource.h加入工程後:

d)修改編輯resource.h和DispECG_ENG.rc

  d.1)將檔案頭的註釋“Used by DispECG_ENG.rc”修改為“Used by DispECG_ENG.rc”

  d.2)修改資原始檔DispECG_ENG.rc,將

  "#include ""res\\DispECG.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 ""res\\DispECG_ENG.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"

需要說明的是:MFC中含有一些預定義好的資源,不同的語言版本儲存在不同的目錄下,英文版儲存在MFC\Include下,其它語言的版本則儲存在Include的子目錄中,譬如中文版對應的目錄為l.chs,日文版對應l.jpn,韓文版對應l.kor,等等。

e)使用視覺化編輯環境編輯對話方塊、選單、字串、版本等語言依賴性資源,將中文版翻譯為英文版。當然,如果對資原始檔的結構非常瞭解,可使用文字編輯器對資原始檔直接編輯。方法是:使用“File\Open…”開啟檔案對化框,找到“DispECG_ENG.rc”,注意開啟方式選擇“Text”。

完成文字的翻譯是一項費時耗力的體力活兒,請耐心地仔細地一一做完。

f)修改工程設定,調整編譯後DLL檔案的存放位置。

由於按照預設的工程設定,DispECG_ENG.DLL的Release版自動生成在D:\My Project\DispECG\DispECG_ENG\Release下,Debug版自動生成在D:\My Project\DispECG\DispECG_ENG\Debug下。為了程式的處理方便,資源DLL最好和應用程式的可執行檔案存放在同一目錄。為做到這一點,請修改工程配置。

方法:操作選單“Project\Project Settings…”

在“Project Settings”中選擇“DispECG_ENG”工程,再選擇“Link”頁面,將輸出檔名由“Release/DispECG_ENG.dll”修改為“../Release/DispECG_ENG.dll”,這樣編譯後生成的DLL檔案將儲存在D:\My Project\DispECG\Release下。

除錯版也作類似的修改,使得編譯後生成的DLL檔案將儲存在D:\My Project\DispECG\Debug下。

g)編譯DispECG_ENG工程,生成發行版和除錯版的DispECG_ENG.DLL。

在編譯資源DLL時別忘了在連線時加上/NOENTRY選項以告訴聯結器這是一個唯一資源的DLL,不包含程式執行的入口點。

(三)在程式中新增多語言支援程式

a) 定義資源名稱

在DispECG工程中的StdAfx.h中新增:

        #define CHINESE          0

        #define    ENGLISH              1

b)定義兩個全域性變數,一個表示當前的語言選擇,另一個為資源控制代碼。

        UINT nLanguage = ENGLISH;

        HINSTANCE hResourceHandle = NULL;

c)新增資源DLL載入程式

在完成應用程式初始化的BOOL CDispECGApp::InitInstance()中新增依據語言選擇資源DLL的程式程式碼。

        nLanguage = GetProfileInt("SETTINGS","LANGUAGE",ENGLISH);

        if (nLanguage != CHINESE)

        {

                CString strFile;

                strFile = "NewDispECG_ENG.dll";

hResourceHandle = AfxLoadLibrary(strFile);

                ASSERT(hResourceHandle);

                if (hResourceHandle)

                {

                        AfxSetResourceHandle(hResourceHandle);

                }

                else

                {

                        CString strText;

                        strText.Format("%s not found!",strFile);

                        ::MessageBox(NULL,strText,"Error",MB_OK|MB_ICONERROR);

                        return FALSE;

                }

        }

d)新增資源DLL解除安裝程式

        CDispECGApp::~CDispECGApp()

        {

                if (hResourceHandle)

                AfxFreeLibrary(hResourceHandle);

        }

e) 新增語言選擇選單和命令實現程式碼。

同步更新各種版本的資源,編輯選單加入語言選擇選單項。注意同一選單項不同語言版本的命令ID保持一致。

使用類嚮導新增命令響應:

        void CDispECGApp::OnSwitchVersion()

        {

                WriteProfileInt("SETTINGS","LANGUAGE",1-nLanguage);

               AfxMessageBox(ID_SWITCH_VERSION);

                TRACE("%s\n%s\n%d\n

                %s\n",m_pszAppName,m_lpCmdLine,m_nCmdShow,m_pszExeName);

        }

(四)修改程式程式碼,根據資源ID呼叫資源

如果原先的程式未考慮到多語言支援,在顯示提示資訊時可能使用如下的語句:

        AfxMessageBox("檔案無法開啟!");

此時應該將諸如"檔案無法開啟!"此類的字串新增到字串資源中,其它語言版本同步更新。同樣,注意字串ID的彼此一致。一個好的習慣是,各版本的資源同步更新後,使用VC開發環境自帶的WinDiff.exe對各個版本下的resource.h進行檔案內容比較,以確保各語言的資源ID彼此完全一致。

修改完畢後,改用根據資源ID進行資源訪問的函式。在實際程式設計中,最常用到的是對字串資源的訪問以及提示資訊的顯示,所以下面這些函式在需多語言支援的應用程式中會常被使用:

int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) -1 );

BOOL LoadString( UINT nID );

void Format( UINT nFormatID, ... );

void FormatMessage( UINT nFormatID, ... );

...

至於其它資源,比如對話方塊、選單等,通常由系統自動完成載入,無需程式設計師在軟體中進行特別處理。