使用<<多国语言字符串操作类>> http://blog.csdn.net/lostspeed/article/details/8520284, 在UI中使用多国语言
工程下载点: srcCipherUI_V2013_0120_1801.rar
效果图:
英国英语UI
简体中文UI
当扩展其他语言的支持, 增加对应语系的语言资源. 资源文件采用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); }
实际应用时, 是用户选择多国语言菜单后, 执行
CLanguageRes::UseLanguageId(false, xx_languageId);
调试的时候, 发现有几百字节的内存泄漏, 在工程中加入了VLD, 超好用, 在Debug模式下运行一次, 退出后, 就看到哪泄漏了.
VLD工程是开源的 VLD 下载, .