MFC 应用程序语言切换

在开发多语言支持的 MFC 应用程序时,如何实现动态语言切换是一个常见的问题。在本文中,我们将介绍两种实现语言切换的方式,并讨论其优缺点。同时,我们还会介绍如何通过保存配置文件来记住用户的语言选择,以及如何在程序启动时加载该语言设置。


第一种方式:通过资源切换实现语言切换

基本思路

在这种方式中,通过将应用程序的主要资源文件扩展为多语言版本(如中文和英文),并在程序运行时根据需要加载对应的资源来实现语言切换。

实现步骤

  1. 资源文件的多语言版本创建

    • 为每种语言创建独立的资源文件版本(如简体中文和英文)。
    • 在资源视图中添加各自的语言对话框和字符串表。
  2. 加载对应语言的资源

    • 使用 SetThreadUILanguageSetThreadLocale 动态设置线程的语言和区域设置。
    • 在应用程序启动时,根据语言配置文件选择合适的资源。
  3. 保存语言配置文件

    • 使用 .ini 文件保存用户选择的语言。

    • 例如:

      ini 复制代码
      [Settings]
      Language=zh-CN

优点

  • 易于实现,直接利用 MFC 的多语言资源支持。
  • 无需动态加载外部 DLL。

缺点

  • 程序体积较大,因为所有语言的资源都嵌入在一个 EXE 文件中。
  • 无法动态扩展语言,需要重新编译程序。

第二种方式:通过资源动态库实现语言切换

基本思路

在这种方式中,将每种语言的资源文件提取到独立的 DLL 文件中,程序运行时根据用户选择动态加载对应的资源 DLL。这样可以实现程序的轻量化,并支持动态扩展语言包。

实现步骤

  1. 创建语言资源动态库

    • 创建多个独立的资源 DLL 项目,例如 MFCApplication_en.dllMFCApplication_zh.dll
    • 每个 DLL 包含对应语言的资源。
  2. 动态加载资源库

    • 在程序运行时,使用 AfxLoadLibrary 动态加载指定的资源 DLL。
    • 使用 AfxSetResourceHandle 设置当前使用的资源句柄。
  3. 保存语言配置文件

    • 与第一种方式类似,使用 .ini 文件保存用户选择的语言。

优点

  • 程序体积较小,每种语言的资源独立存储。
  • 支持动态扩展语言,只需添加新的 DLL 即可。

缺点

  • 实现复杂度较高,需要处理 DLL 的加载与释放。
  • 程序运行时依赖外部资源文件(DLL)。

保存语言设置并实现自动加载

无论使用哪种方式,都需要保存用户的语言选择,并在程序启动时自动加载对应的语言设置。

初始化和退出实例

程序启动时自动加载;程序退出时释放资源库:

cpp 复制代码
// CMFCApplicationApp 初始化

BOOL CMFCApplicationApp::InitInstance()
{
	// 省略......
	
	// 加载语言配置
	CString language = LoadLanguageFromIni();
	SetLanguage(language);

	// 省略......
	return FALSE;
}

int CMFCApplicationApp::ExitInstance()
{
	if (g_hCurrentResource != NULL) {
		FreeLibrary(g_hCurrentResource);	// 释放当前资源库
		g_hCurrentResource = NULL;			// 清空资源句柄
	}
	return CWinApp::ExitInstance();
}

保存语言到 .ini 文件

以下代码用于保存用户选择的语言到 .ini 文件:

cpp 复制代码
void CMFCApplicationApp::SaveLanguageToIni(const CString& language)
{
    // 获取当前执行文件的目录
    TCHAR szPath[MAX_PATH];
    GetModuleFileName(NULL, szPath, MAX_PATH);
    CString strPath = szPath;
    strPath = strPath.Left(strPath.ReverseFind('\\')) + _T("\\Settings.ini");

    // 保存语言配置到 .ini 文件
    WritePrivateProfileString(_T("Settings"), _T("Language"), language, strPath);
}

加载语言设置

在应用程序启动时,读取 .ini 文件,加载对应的语言设置:

cpp 复制代码
CString CMFCApplicationApp::LoadLanguageFromIni()
{
    TCHAR szPath[MAX_PATH];
    GetModuleFileName(NULL, szPath, MAX_PATH);
    CString strPath = szPath;
    strPath = strPath.Left(strPath.ReverseFind('\\')) + _T("\\Settings.ini");

    TCHAR szLanguage[16] = { 0 };
    GetPrivateProfileString(_T("Settings"), _T("Language"), _T("en-US"), szLanguage, 16, strPath);

    return CString(szLanguage);
}

设置语言

在应用程序启动时,设置语言的两种方式:

cpp 复制代码
void CMFCApplicationApp::SetLanguage(const CString& language)
{
#if 1
	LANGID idLang = 0;

	if (language == _T("zh-CN")) {
		idLang = MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT);
	}
	else if (language == _T("en-US")) {
		idLang = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
	}

	if (idLang != 0) {
		SetThreadUILanguage(idLang);
		SetThreadLocale(idLang);
	}
#else
	CString strLanguage;
	if (language == _T("zh-CN")) {
		strLanguage.Format(_T("MFCApplication_zh.dll"));
	}
	else if (language == _T("en-US")) {
		strLanguage.Format(_T("MFCApplication_en.dll"));
	}

	// 加载新的资源库
	g_hCurrentResource = AfxLoadLibrary(strLanguage);

	// 设置新的资源句柄
	if (g_hCurrentResource != NULL) {
		AfxSetResourceHandle(g_hCurrentResource);
	}
#endif // 0
}

实现语言切换后自动重启

为了应用新的语言设置,可以在用户切换语言后重启应用程序:

重启实现代码

在主对话框中,当用户点击按钮切换语言后,保存设置并触发程序重启:

cpp 复制代码
void CMFCApplicationDlg::OnBnClickedButtonTestCN()
{
    theApp.SaveLanguageToIni(_T("zh-CN"));

    m_bRestartFlag = TRUE;
    PostMessage(WM_CLOSE, 0, 0);
}

void CMFCApplicationDlg::OnBnClickedButtonTestUS()
{
    theApp.SaveLanguageToIni(_T("en-US"));

    m_bRestartFlag = TRUE;
    PostMessage(WM_CLOSE, 0, 0);
}

void CMFCApplicationDlg::OnClose()
{
    if (m_bRestartFlag) {
        CString strFileName = _T("");
        GetModuleFileName(NULL, strFileName.GetBuffer(MAX_PATH), MAX_PATH);
        ShellExecute(NULL, _T(""), strFileName, NULL, NULL, SW_SHOWNORMAL);
        strFileName.ReleaseBuffer();
    }
    CDialogEx::OnClose();
}

总结

通过上述两种方式,可以实现 MFC 应用程序的多语言支持:

  • 方式一适用于语言资源固定、无需动态扩展的情况。
  • 方式二适用于需要动态扩展语言资源的情况。
  • 文件化存储方式
    • 将所有控件的 ID 和文本保存到文件中(例如 .ini 或 .json 文件)。
    • 程序运行时动态加载文件内容,更新控件的文本。
    • 无需重启即可切换语言。

通过保存用户选择的语言设置,并在程序启动时加载对应的语言,用户可以获得无缝的多语言体验。同时,结合程序的重启机制,可以确保语言切换后的即时生效。

相关推荐
高一学习c++会秃头吗7 分钟前
string
开发语言·c++
蓝天扶光1 小时前
C++算法第十一天
开发语言·c++·算法
木向3 小时前
leetcode17:电话号码的字母组合
开发语言·c++·算法
A_New_World3 小时前
BlockDeque
开发语言·c++
重生之我在字节当程序员3 小时前
解释工厂模式
开发语言·c++·简单工厂模式
SunshineBooming4 小时前
qemu源码解析【05】qemu启动初始化流程
c++·驱动开发·源码软件
哎呦,帅小伙哦5 小时前
std::async 和 std::packaged_task
c++
XYLoveBarbecue7 小时前
C++ 只出现一次的数字 - 力扣(LeetCode)
开发语言·c++·leetcode
奔跑de自由7 小时前
深入剖析 C 语言数组类型差异:指针视角下的奇妙世界
c语言·c++·算法