close
文章出處

此隨筆中主要內容來自http://blog.csdn.net/china_hxx/article/details/10066655,原出處不詳。

    以下內容基于VC 6.0。要實現界面多語言化,必須要先配置項目使其支持Unicode編碼,文章《VC下的Unicode編程》 對此有詳細介紹。

    首先創建一個基于MFC的工程,在選擇語言時選擇 中文[簡體,中國]。

    項目框架選擇對話框、單文檔和多文檔都可以,這里就選個基于對話框的吧,然后立即修該項目屬性使其支持Unicode。

    MFC已經為我們加入了一些資源,包括2個對話框、1個String Table等。為了節省空間修改了對話框的大小。

    現在項目中的資源情況如下:

    然后再新建一個DLL項目,為了方便管理可以將其添加到當前工作空間中。

    立即修改此DLL項目使其支持Unicode,然后設置項目依賴性(Project->Dependencies…) ,資源DLL要在exe項目之前編譯:

    為了將生成的資源DLL自動拷貝到exe項目執行目錄下,還需要修改DLL項目的Post-build Step:

    然后將主項目目錄下的res文件夾、resource.h、TestMultiLang.rc文件拷貝到ResENG項目目錄下,res文件夾和resource.h直接替換,將ResENG.rc刪除后再將TestMultiLang.rc重命名為ResENG.rc。

    切換到資源視圖就會發現這兩個項目的資源內容是一樣的了,將ResENG項目的資源更改為英文如下:

    為了讓程序在啟動的時候加載英文語言資源,需要在CTestMultiLangApp::InitInstance()函數中Dlg創建之前添加如下語句:

HINSTANCE hLanguageDll = AfxLoadLibrary(_T("ResENG")); if (hLanguageDll) AfxSetResourceHandle(hLanguageDll);

 

    最后重新編譯TestMultiLang項目,運行就會發現對話框已經是英文界面了 :)

 

    

動態實現語言切換

    以上程序僅為示例,為了能使程序自動選擇合適的語言,還需要做許多工作。比如要在程序中添加程序語言切換菜單或語言選擇下拉列表框,并將用戶喜好保存在ini配置文件中,然后在程序啟動時自動讀取此ini文件加載相應的資源DLL;如果用戶未設置語言,則默認根據操作系統語言加載合適資源,如果不存在針對此語言的資源DLL,就使用最國際化的語言——英語。

    在stdafx.h中做如下定義:

#define CHINESE    0
#define ENGLISH    1

    在CTestMultiLangApp類中添加private變量 int m_Lang, 用來保存當前語言類型是CHINESE,還是ENGLISH。

    在CTestMultiLangApp類中添加public方法GetLang用于返回當前語言類型。

int CTestMultiLangApp::GetLang(void)
{
    return m_Lang;
}

    根據配置加載相應資源的DLL包裝成一個函數如下:

void CTestMultiLangApp::LoadLanguage(void)
{
    CString strDLL;
    HINSTANCE hLanguageDll, hLanguageNow;

    //保存本身的資源句柄
    static HINSTANCE hOriginalHandle = ::AfxGetResourceHandle(); 

    //讀取ini配置文件
    CString strFileName = _T("Language.ini");
    if (PathFileExists(strFileName))
     {          
        int lang = 0;
        CFile file;
        file.Open(strFileName, CFile::modeRead | CFile::typeBinary);
        file.Read(&lang, sizeof(lang));
        file.Close();
        m_Lang = lang;
     }
    
    //根據用戶喜好來設置
    if (m_Lang == ENGLISH)//英文
        hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
    else if (m_Lang == CHINESE)//中文
        hLanguageDll = hOriginalHandle;
    else
    {
        //用戶未指定,則根據系統選擇合適語言,默認為英文
        WORD wLangPID = PRIMARYLANGID(GetSystemDefaultLangID()); 
        if (wLangPID == LANG_CHINESE)
            hLanguageDll = hOriginalHandle;
        else if (wLangPID == LANG_ENGLISH)
            hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
        else
            hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
    } 
    //保存已加載的資源DLL句柄
    hLanguageNow = ::AfxGetResourceHandle(); 
    //加載新的資源DLL
    if(hLanguageDll)
        ::AfxSetResourceHandle(hLanguageDll); 
    //釋放之前加載的資源DLL
    if (hLanguageNow != hOriginalHandle)
        FreeLibrary(hLanguageNow);
}

    因為在切換界面語言的過程中需要頻繁地銷毀和創建對話框,所以我們也把創建對話框的代碼包裝成一個函數:

void CTestMultiLangApp::OpenWindow(void)
{
    CTestMultiLangDlg dlg;
    m_pMainWnd = &dlg; 
    dlg.DoModal();
}

    現在在InitInstance()函數里簡單得調用一下這兩個函數就可以了:

BOOL CTestMultiLangApp::InitInstance()
{
    AfxEnableControlContainer();
 
    #ifdef _AFXDLL
    Enable3dControls(); // Call this when using MFC in a shared DLL
    #else
    Enable3dControlsStatic(); // Call this when linking to MFC  statically
    #endif
 
    LoadLanguage();
 
    if (!OpenWindow())
        return FALSE;
 
    return FALSE;
}

    然后要實現用戶界面的語言選擇消息響應函數。該函數要將用戶的選擇保存到ini文件里,銷毀當前窗口,然后再重新加載資源并創建新的窗口:

 

void CTestMultiLangDlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知處理程序代碼
    CTestMultiLangApp*pApp = (CTestMultiLangApp*)AfxGetApp();

    int old_Lang = pApp->GetLang();
    int new_Lang = 0;
    if(old_Lang == ENGLISH)
        new_Lang = CHINESE;
    else
        new_Lang = ENGLISH;

    CFile file;
    file.Open(_T("Language.ini"), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary);
    file.Write(&new_Lang, sizeof(new_Lang));
    file.Close();
     
    //銷毀當前窗口    
    pApp->m_pMainWnd = NULL;
    this->DestroyWindow();
     
    //創建新的窗口
    pApp->LoadLanguage();
    pApp->OpenWindow();
}

 

    上面這段代碼中pApp->m_pMainWnd = NULL這一句是關鍵,它切斷了銷毀當前程序消息向上的路由,因此進程不會被銷毀,才有了機會重新創建新的窗口。如果項目是基于單文檔/多文檔的程序的話,還要加一句pApp->m_pDocManager = NULL才可以。
    重新編譯項目,現在語言就可以動態切換了。

繼續添加其他語言

    如果項目不僅要支持中英文這兩種語言,比如還需要支持德語,這里介紹兩種方法來實現。

    第一種方法顯而易見————新建一個資源DLL項目。理論上這是可行的,但是有個棘手的問題:如果需要支持的語言很多,那么對程序資源的任何更改都需要同步更新到其他所有資源項目!
    第二種方法是借用工具,由一個資源DLL制作出其他各語言版本的資源DLL。這個工具軟件會把資源DLL中的字符串、對話框、菜單項等資源提取出來并保存到一個po文件里,之后使用poedit就可以進行翻譯了。翻譯完成后再根據此po文件和原資源DLL生成新的資源DLL。
    工具軟件截圖如下:


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()