experiment: UI中的资源字符串国际化

使用<<多国语言字符串操作类>> http://blog.csdn.net/lostspeed/article/details/8520284, 在UI中使用多国语言

工程下载点: srcCipherUI_V2013_0120_1801.rar

效果图:

英国英语UI

experiment: UI中的资源字符串国际化_第1张图片

简体中文UI

experiment: UI中的资源字符串国际化_第2张图片


Demo中使用的多国语言集合 : 简体中文, 英国英语.

当扩展其他语言的支持, 增加对应语系的语言资源. 资源文件采用UnicodeIni文件存储.

默认的国际化语言是本地化语言, 可以指定UI要使用的语言.

    /// @fn         UseLanguageId
    /// @brief      指定使用的国际化语言
    /// @param      bool bLocalLanguage, true = 语言ID是本地语言, false = 可以指定使用的语言
    /// @param      由MAKELANGID宏指定的语言ID, 当(true != bLocalLanguage)时, 一定要指定语言ID
    ///             e.g. 在中文下使用英文的UI
    void UseLanguageId(bool bLocalLanguage = true, DWORD dwLangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
void CLanguageRes::UseLanguageId(bool bLocalLanguage, DWORD dwLangId)
{
    m_dwLanguageId = bLocalLanguage ? GetUserDefaultUILanguage() : dwLangId;
    m_bFindLocalLanguageRes = FindLanguageId(m_dwLanguageId);
    m_strLocalLanguageSection = GetLanguageSectionById(m_dwLanguageId);
}

定义了资源ID录入宏, 方便载入和使用资源ID

/// 转换窗体本身的国际化资源 e.g. 窗体标题
#define CONVERT_LANG_RES_WND(pLanguageRes, hWnd, resId) \
    if (NULL != (pLanguageRes)) \
    ::SetWindowText((hWnd), (pLanguageRes)->LangResLoadString(L#resId).c_str());

/// 转换给定窗体控件的国际化资源 e.g. 对话框的 IDOK 按钮
#define CONVERT_LANG_RES_CTRL(pLanguageRes, hWnd, resId) \
    if (NULL != (pLanguageRes)) \
    ::SetDlgItemText((hWnd), (resId), (pLanguageRes)->LangResLoadString(L#resId).c_str());

载入资源字符串简洁.

void CAboutDlg::convertLangRes()
{
    CONVERT_LANG_RES_WND(LangResGet(), this->m_hWnd, IDD_SRCCIPHERUI_DIALOG);

    CONVERT_LANG_RES_CTRL(LangResGet(), this->m_hWnd, IDC_STATIC_PROG_INFO);
    CONVERT_LANG_RES_CTRL(LangResGet(), this->m_hWnd, IDC_STATIC_COPY_RIGHT);
    CONVERT_LANG_RES_CTRL(LangResGet(), this->m_hWnd, IDOK);
}
定义了程序中支持的国际化语言结构数组, 方便维护

#pragma pack(1)

typedef struct _tag_LanguageId
{
    DWORD   wPrimLangId;    ///< Prim. lang. symbol
    DWORD   wSubLangId;    ///< Sublang. symbol

    _tag_LanguageId()
    {
        this->wPrimLangId = 0;
        this->wSubLangId = 0;
    }

    _tag_LanguageId(WORD wPrimLangId, WORD wSubLangId)
    {
        this->wPrimLangId = wPrimLangId;
        this->wSubLangId = wSubLangId;
    }
}TAG_LANGUAGE_ID;

#pragma pack()

const TAG_LANGUAGE_ID g_arrLanguageId[] = 
{
    TAG_LANGUAGE_ID(LANG_CHINESE_SIMPLIFIED,SUBLANG_CHINESE_SIMPLIFIED),    ///< 简体中文
    TAG_LANGUAGE_ID(LANG_ENGLISH, SUBLANG_ENGLISH_US),                      ///< 英文
};

资源文件的录入, Demo中采用直接生成资源文件. 实际应用时, 应建立另外的资源录入程序.

CLanguageRes *  g_pLangRes  =   NULL;

void CreateLangRes()
{
    std::wstring    strLangResPathName  =   L"";

    strLangResPathName = GetTheModulePath();
    strLangResPathName += L"LangRes.ini";
    g_pLangRes = new CLanguageRes((wchar_t *)strLangResPathName.c_str());
    _ASSERT(NULL != g_pLangRes);

#ifdef ONLY_USE_ENGLISH
    /// 如果不管操作系统代码页如何, 都要使用英文. 指定语言ID
    /// 可以由用户在程序菜单上的语言ID列表选择后, 执行设置语言ID
    g_pLangRes->UseLanguageId(false, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
#endif
}

void BuildLangRes()
{
      ///< 制作国际化资源, 只需一次, 有了国际化资源文件后, 注释掉 NEED_MAKE_LANGUAGE_RESOUCE
#ifdef NEED_MAKE_LANGUAGE_RESOUCE
    DWORD           dwLangIdCn          =   MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED);
    DWORD           dwLangIdEn          =   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);

    _ASSERT(NULL != g_pLangRes);

    /// 建立多语言条目, 建立完成后,以后可以手工在语言文件中添加, 或做个语言文件录入程序

    /// 制作中文资源, 英文资源, ...

//     #define IDM_ABOUTBOX                    0x0010

//     #define IDD_ABOUTBOX                    100

//     #define IDS_ABOUTBOX                    101
    g_pLangRes->LangResSaveString(L"IDS_ABOUTBOX", L"关于...", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDS_ABOUTBOX", L"about ...", dwLangIdEn);

//     #define IDD_SRCCIPHERUI_DIALOG          102
    g_pLangRes->LangResSaveString(L"IDD_SRCCIPHERUI_DIALOG", L"加解密算法UI", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDD_SRCCIPHERUI_DIALOG", L"CipherUI", dwLangIdEn);

//     #define IDR_MAINFRAME                   128

//     #define IDC_BTN_LOAD_PLAINTEXT          1000
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_PLAINTEXT", L"载入明文", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_PLAINTEXT", L"load plaintext", dwLangIdEn);

//     #define IDC_BTN_CIPHER                  1001
    g_pLangRes->LangResSaveString(L"IDC_BTN_CIPHER", L"加密", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_BTN_CIPHER", L"Encrypt", dwLangIdEn);

//     #define IDC_BTN_LOAD_CIPHERTEXT         1002
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_CIPHERTEXT", L"载入密文", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_CIPHERTEXT", L"Load Cipher text", dwLangIdEn);

//     #define IDC_BTN_LOAD_KEY                1003
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_KEY", L"载入密钥", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_BTN_LOAD_KEY", L"Load Key text", dwLangIdEn);

//     #define IDC_BTN_DECRYPT                 1004
    g_pLangRes->LangResSaveString(L"IDC_BTN_DECRYPT", L"解密", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_BTN_DECRYPT", L"decrypt", dwLangIdEn);

//     #define IDC_STATIC_PLAINTEXT            1005
    g_pLangRes->LangResSaveString(L"IDC_STATIC_PLAINTEXT", L"明文", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_PLAINTEXT", L"plaintext", dwLangIdEn);

//    #define IDC_STATIC_CIPHERTEXT           1014
    g_pLangRes->LangResSaveString(L"IDC_STATIC_CIPHERTEXT", L"密文", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_CIPHERTEXT", L"ciphertext", dwLangIdEn);

//     #define IDC_EDIT_PLAINTEXT              1006

//     #define IDC_EDIT_OTP_KEY                1007

//     #define IDC_EDIT_CIPHERTEXT             1008

//     #define IDC_STATIC_KEY                  1009
    g_pLangRes->LangResSaveString(L"IDC_STATIC_KEY", L"密钥", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_KEY", L"cipher key", dwLangIdEn);

//     #define IDC_STATIC_ENCRYPT              1010
    g_pLangRes->LangResSaveString(L"IDC_STATIC_ENCRYPT", L"加密", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_ENCRYPT", L"encrypt", dwLangIdEn);

//     #define IDC_STATIC_DECRYPT              1011
    g_pLangRes->LangResSaveString(L"IDC_STATIC_DECRYPT", L"解密", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_DECRYPT", L"dncrypt", dwLangIdEn);

//     #define IDC_STATIC_PROG_INFO            1012
    g_pLangRes->LangResSaveString(L"IDC_STATIC_PROG_INFO", L"加解密算法UI", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_PROG_INFO", L"cipher Algorithm ui", dwLangIdEn);

//     #define IDC_STATIC_COPY_RIGHT           1013
    g_pLangRes->LangResSaveString(L"IDC_STATIC_COPY_RIGHT", L"copyleft 2013", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDC_STATIC_COPY_RIGHT", L"copyleft 2013", dwLangIdEn);

    /// 系统内建的ID
    // IDOK
    g_pLangRes->LangResSaveString(L"IDOK", L"确定", dwLangIdCn);
    g_pLangRes->LangResSaveString(L"IDOK", L"OK", dwLangIdEn);

#endif
}

CLanguageRes * LangResGet()
{
    return g_pLangRes;
}

void ReleaseRes()
{
    SAFE_DELETE(g_pLangRes);
}

Demo中选择语言是编译时刻指定, e.g. 中文环境中使用英文UI.

实际应用时, 是用户选择多国语言菜单后, 执行

CLanguageRes::UseLanguageId(false, xx_languageId);

调试的时候, 发现有几百字节的内存泄漏, 在工程中加入了VLD, 超好用, 在Debug模式下运行一次, 退出后, 就看到哪泄漏了.

VLD工程是开源的 VLD 下载, .





你可能感兴趣的:(experiment: UI中的资源字符串国际化)