1. 程式人生 > >VC2008以資源形式實現多語言版本

VC2008以資源形式實現多語言版本

文字 應用程序 ini 標記 完成 cccccc 選擇 否則 nbsp

越來越多的程序支持多語言切換,或者能自動適應當前系統語言,讓自己開發的程序支持多語言不僅可以讓自己的程序被國人使用,也能讓外國程序愛好者使用。VC開發多語言程序有多種方法,或讀取配置文件,或使用不同資源DLL等等。這裏介紹以資源形式實現多語言版本。

1.打開Visual Studio 2008,新建一個基於對話框工程,名稱為LanguageTest,不使用Unicode庫 ,資源語言一共有十種(當前操作系統為Windows 7簡體中文版),如下圖所示:
技術分享圖片
在此選擇“中文(簡體,中國)”,單擊“完成”按鈕。
2.在對話框設計界面上,放置一個按鈕(ID號IDC_SHOW_BUTTON)、一個靜態文本(ID號IDC_TEXT_STATIC,必須改其默認ID號)和一個編輯框(ID號IDC_TEXT_EDIT),資源視圖如下所示:

技術分享圖片
可以看到資源視圖裏面都是簡體中文的資源文件,現在在“String Table”字符串表類型下,雙擊打開其子項“String Table”,默認只有一條字符串,是窗口菜單裏的“關於 LanguageTest(&A)...”,如圖所示:
技術分享圖片
現在點一下第二行(以黑色外框標誌),新建一條字符串(值會默認增長,註意不要與已有的沖突),“標題”是“ID”號所代表的字符串內容,我們增加字符串如下圖所示:
技術分享圖片
3.在“解決方案管理器”下雙擊打開“LanguageTestDlg.cpp”文件,在其初始化函數OnInitDialog()增加如下紅色代碼:

BOOL CLanguageTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// 將“關於...”菜單項添加到系統菜單中。

// IDM_ABOUTBOX 必須在系統命令範圍內。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX );
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
// 執行此操作
SetIcon(m_hIcon, TRUE); // 設置大圖標
SetIcon(m_hIcon, FALSE); // 設置小圖標

// TODO: 在此添加額外的初始化代碼
CString strTemp;
strTemp.LoadString(IDS_SHOWBUTTON); //LoadString讀取一個ID號定義的字符串資源
SetDlgItemText(IDC_SHOW_BUTTON,strTemp);

strTemp.LoadString(IDS_TEXTSTATIC);
SetDlgItemText(IDC_TEXT_STATIC,strTemp);

strTemp.LoadString(IDS_TEXTEDIT);
SetDlgItemText(IDC_TEXT_EDIT,strTemp);
return TRUE; // 除非將焦點設置到控件,否則返回 TRUE
}

編譯運行,結果如下圖所示:
技術分享圖片
4.制作英文版的“String Table”。右擊“資源視圖”下的“String Table”子項,選擇“插入副本”,在彈出的對話框選擇“英語(美國)”,如下圖所示:
技術分享圖片
“確定”按下之後,就會多出一個字符串資源來,並且在後面名稱多了標記“[英語(美國)]”,雙擊打開其內容與簡體中文字符串資源一樣,如下圖所示:
技術分享圖片
將所有字符串修改“標題”內容為英文,如下圖所示:
技術分享圖片
再編譯生成,此時應用程序就能適應簡體中文操作系統和英文美國操作系統了,會自動顯示為默認操作系統語言。可是由於此時沒有英文版系統可以驗證,無法確定是否完全正確,待以後驗證。
5.接下去,欲使用SetThreadLocale自由切換程序界面語言,在應用程序類初始化函數InitInstance()添加如下代碼:

SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT));

運行程序,出現問號亂碼情況,當前Windows 7系統的顯示語言只有“中文(簡體)”,而“當前系統區域設置”為“中文(簡體,中國)”,如下圖所示:

技術分享圖片

自由切換語言失敗,參考MSDN幫助文檔,對的介紹說明:http://msdn.microsoft.com/en-us/library/dd374051%28VS.85%29.aspx

Windows Vista and later: Do not use SetThreadLocale to select a user interface language. The resource loader selects the resource that is defined in the .rc file with a LANGUAGE statement, or the application can use FindResourceEx. Additionally, the application can use SetThreadUILanguage.

Windows 2000, Windows XP: Do not use SetThreadLocale to select a user interface language. To select the resource that is defined in the .rc file with a LANGUAGE statement, the application must use the FindResourceEx function.

另有一篇文章討論SetThreadLocale no longer changes GUI language in Vista http://social.msdn.microsoft.com/Forums/en/windowscompatibility/thread/d3a44b1c-900c-4c64-bdf8-fe94e46722e2

替換成如下代碼:

SetThreadUILanguage(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));

運行發現可以顯示“英文”資源字符串,如下圖所示:
技術分享圖片
可以使用GetUserDefaultUILanguage()判斷當前用戶界面語言,如下當用戶界面語言為“簡體中文”時,設置為“英文(美國)”:

if (GetUserDefaultUILanguage() == MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED))
{
SetThreadUILanguage(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US));
}


在Windows XP簡體中文版下,非Unicode程序的語言為“中文(中國)”,代碼頁轉換表有包含“US-ASCII”,在Windows 7下未找到“代碼頁轉換表”,使用SetThreadLocale和SetThreadUILanguage(註:靜態鏈接然後到XP下測試的 )都能將用戶界面語言設置成“英文(美國)”,如下圖所示:

技術分享圖片

改變“控制面板”裏面的“區域選項”語言為“英語(美國)”,則顯示成問號,原因在於SetThreadLocale設置的語言與“區域選項”裏面的語言一樣,若是一樣,則不操作,如下圖所示:

技術分享圖片

在此中英文版本資源下,在中英文系統語言環境下,就會自動切換不同語言資源,然後在另外系統語言環境下(如:日語),就設定程序語言為英文(英文在大多數系統下都支持),代碼如下:(未能完全測試)

if ((GetSystemDefaultLangID() != MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) &&
        (GetSystemDefaultLangID() != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)))
{
    OSVERSIONINFO ovs;
    ovs.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (::GetVersionEx(&ovs))
    {
        if (ovs.dwPlatformId == VER_PLATFORM_WIN32_NT && ovs.dwMajorVersion >= 6 &&
                ovs.dwMinorVersion >= 0)
        {
            SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
        }
        else
            SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
    }
}
參考資料:

1.編寫 Win32 多語言用戶界面應用程序 http://msdn.microsoft.com/zh-cn/goglobal/bb688160
2.SetThreadUILanguage http://msdn.microsoft.com/en-us/library/dd374053%28VS.85%29.aspx
3.SetThreadLocale http://msdn.microsoft.com/en-us/library/dd374051%28VS.85%29.aspx
4.語言標識符常量和字符串 http://msdn.microsoft.com/en-us/library/dd318693%28VS.85%29.aspx
5.LoadString的如何確定load哪個語言的資源?http://topic.csdn.net/u/20080504/15/fb71cf4e-8420-4c1d-b89e-2784ba3dfca9.html

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!http://www.captainbed.net

VC2008以資源形式實現多語言版本