当前位置: 首页 > article >正文

MFC 应用程序语言切换

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


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

基本思路

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

实现步骤

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

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

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

    • 使用 .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)。

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

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

初始化和退出实例

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

// 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 文件:

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 文件,加载对应的语言设置:

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);
}

设置语言

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

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
}

实现语言切换后自动重启

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

重启实现代码

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

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 文件)。
    • 程序运行时动态加载文件内容,更新控件的文本。
    • 无需重启即可切换语言。

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


http://www.kler.cn/a/444748.html

相关文章:

  • uniapp图片数据流���� JFIF ��C 转化base64
  • SQL语句自动加上了LIMIT 10,导致报错
  • 二八(vue2-04)、scoped、data函数、父子通信、props校验、非父子通信(EventBus、provideinject)、v-model进阶
  • 浅谈目前我开发的前端项目用到的设计模式
  • Linux 文件系统目录结构及其简要介绍
  • 怎么将pdf中的某一个提取出来?介绍几种提取PDF中页面的方法
  • #Java篇:java项目init和写接口流程步骤详细
  • UG NX二次开发(C#)-如何设置UGOpen的UF_CAM_geom_type_e枚举类型
  • Go语言封装Cron定时任务
  • 【c++丨STL】set/multiset的使用
  • 2025年NISP考试时间是什么时候?NISP要多少钱?NISP考试时间及费用超全解说!
  • tryhackme-Pre Security-HTTP in Detail(HTTP的详细内容)
  • 2024159读书笔记|《南山册页:齐白石果蔬册鱼虫册》节选
  • 【Rust自学】4.3. 所有权与函数
  • WPF+MVVM案例实战与特效(四十三)- 打造动态炫酷彩虹字控件,让你的界面动起来
  • SQLite 命令
  • 亚信安全春节14天双倍假期通告
  • 在 Windows 上添加 github SSH 密钥
  • Unity录屏插件-使用Recorder录制视频
  • vscode不同的项目使用不同的环境变量或编译环境
  • 《小米创业思考》
  • 【数据库系列】MongoTemplate 基本入门:MongoDB 的增删改查
  • Ubuntu搭建ES8集群+加密通讯+https访问
  • 灯光开关切换(c++)
  • 实现 WebSocket 接入文心一言
  • Spring Boot 项目创建