MFC 应用程序语言切换
在开发多语言支持的 MFC 应用程序时,如何实现动态语言切换是一个常见的问题。在本文中,我们将介绍两种实现语言切换的方式,并讨论其优缺点。同时,我们还会介绍如何通过保存配置文件来记住用户的语言选择,以及如何在程序启动时加载该语言设置。
第一种方式:通过资源切换实现语言切换
基本思路
在这种方式中,通过将应用程序的主要资源文件扩展为多语言版本(如中文和英文),并在程序运行时根据需要加载对应的资源来实现语言切换。
实现步骤
-
资源文件的多语言版本创建:
- 为每种语言创建独立的资源文件版本(如简体中文和英文)。
- 在资源视图中添加各自的语言对话框和字符串表。
-
加载对应语言的资源:
- 使用
SetThreadUILanguage和SetThreadLocale动态设置线程的语言和区域设置。 - 在应用程序启动时,根据语言配置文件选择合适的资源。
- 使用
-
保存语言配置文件:
- 使用
.ini文件保存用户选择的语言。 - 例如:
[Settings] Language=zh-CN
- 使用
优点
- 易于实现,直接利用 MFC 的多语言资源支持。
- 无需动态加载外部 DLL。
缺点
- 程序体积较大,因为所有语言的资源都嵌入在一个 EXE 文件中。
- 无法动态扩展语言,需要重新编译程序。
第二种方式:通过资源动态库实现语言切换
基本思路
在这种方式中,将每种语言的资源文件提取到独立的 DLL 文件中,程序运行时根据用户选择动态加载对应的资源 DLL。这样可以实现程序的轻量化,并支持动态扩展语言包。
实现步骤
-
创建语言资源动态库:
- 创建多个独立的资源 DLL 项目,例如
MFCApplication_en.dll和MFCApplication_zh.dll。 - 每个 DLL 包含对应语言的资源。
- 创建多个独立的资源 DLL 项目,例如
-
动态加载资源库:
- 在程序运行时,使用
AfxLoadLibrary动态加载指定的资源 DLL。 - 使用
AfxSetResourceHandle设置当前使用的资源句柄。
- 在程序运行时,使用
-
保存语言配置文件:
- 与第一种方式类似,使用
.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 1LANGID 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);}
#elseCString 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 文件)。
- 程序运行时动态加载文件内容,更新控件的文本。
- 无需重启即可切换语言。
通过保存用户选择的语言设置,并在程序启动时加载对应的语言,用户可以获得无缝的多语言体验。同时,结合程序的重启机制,可以确保语言切换后的即时生效。
相关文章:
MFC 应用程序语言切换
在开发多语言支持的 MFC 应用程序时,如何实现动态语言切换是一个常见的问题。在本文中,我们将介绍两种实现语言切换的方式,并讨论其优缺点。同时,我们还会介绍如何通过保存配置文件来记住用户的语言选择,以及如何在程序…...
Swift 的动态性
Swift 的动态性指的是 Swift 编程语言支持运行时操作的一些特性,使得代码的行为能够在运行时作出一定的调整或决策。这些特性通常可以让程序在运行时动态地添加、删除或修改对象的属性、方法等,而不是在编译时完全确定。 Swift 的动态性主要体现在以下几…...
用.Net Core框架创建一个Web API接口服务器
我们选择一个Web Api类型的项目创建一个解决方案为解决方案取一个名称我们这里选择的是。Net 8.0框架 注意,需要勾选的项。 我们找到appsetting.json配置文件 appsettings.json配置文件内容如下 {"Logging": {"LogLevel": {"Default&quo…...
lua dofile 传参数
cat 1.lua arg[1] 111 arg[2] 222 dofile(./2.lua) cat 2.lua print("First argument is: " .. arg[1]) print("Second argument is: " .. arg[2]) 执行 lua 1.lua,结果为: First argument is: 111 Second argument is: 222 l…...
HTML 有效 DOCTYPES
HTML 有效 DOCTYPES 介绍 HTML文档类型定义(DOCTYPE)是HTML文档中的一个声明,它告诉浏览器该文档使用的HTML版本。这有助于浏览器正确地解析和渲染页面。本文将探讨各种有效的HTML DOCTYPE声明,并解释它们的作用。 HTML5 DOCTY…...
岁末回望,追梦远方
又到了岁末年初,按惯例,风云我都会写一篇长长的感悟,给自己辞旧的总结复盘,迎新的追梦定调,今年赋诗一首,畅想一下诗和远方,简洁而又虚无,缥缈中坚定初心。 岁末回首步履深…...
通过阿里云 Milvus 和 LangChain 快速构建 LLM 问答系统
背景介绍 阿里云向量检索 Milvus 版是一款云上全托管服务,确保了与开源Milvus的100%兼容性,并支持无缝迁移。在开源版本的基础上增强了可扩展性,能提供大规模 AI 向量数据的相似性检索服务。相比于自建,目前阿里云Milvus具备易用…...
语音识别失败 chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限
环境: Win10专业版 谷歌浏览器 版本 131.0.6778.140(正式版本) (64 位) 问题描述: 局域网web语音识别出现识别失败 chrome控制台出现下获取浏览器录音功能,因为安全性问题,需要在…...
全域数据集成平台ETL
全域数据集成平台ETL Restcloud 工作原理 RestCloud数据集成平台采用SpringCloud微服务架构技术开发,底层基于纯Java语言采用前后端分离架构,前端采用React技术进行开发。 RestCloud数据集成平台是基于数据流工作流引擎的架构进行研发的,底…...
海外储能电站双向计量表功能参数介绍
摘要 随着全球能源结构的转型和储能技术的发展,对于电力系统的监控和管理提出了更高的要求。ADL3000-E-B 导轨式多功能电能表,由安科瑞电气股份有限公司研发,是一款为电力系统、工矿企业、公用设施设计的智能仪表。本文将从海外储能背景出发…...
javase-15、正则表达式
一、初识正则表达式 1、概念 正则表达式是对字符串操作的一种逻辑公式,它会将事先定义好的一些特定字符,以及这些特定字符的组合,组成一个规则字符串,并且通过这个规则字符串表达对给定字符串的过滤逻辑。 一条正则表达式也称为…...
【SpringSecurity】SpringSecurity+JWT实现登录
1. SpringSecurity介绍 Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。它是为Java应用程序设计的,特别是那些基于Spring的应用程序。Spring Security是一个社区驱动的开源项目,它提供了全面的安全性解决方案,包括防…...
jmeter连接mysql
查询mysql数据库版本 SELECT VERSION(); 下载jmeter mysql 驱动jar包,版本低于mysql版本,放在jmeter的lib 路径下 MySQL :: Download MySQL Connector/J (Archived Versions) 添加JDBC Connection Configuration 填写 variable name 及数据库信息 注意…...
图书馆管理系统(三)基于jquery、ajax
任务3.4 借书还书页面 任务描述 这部分主要是制作借书还书的界面,这里我分别制作了两个网页分别用来借书和还书。此页面,也是通过获取books.txt内容然后添加到表格中,但是借还的操作没有添加到后端中去,只是一个简单的前端操作。…...
Nginx Location 配置块全解析与示例
Nginx Location 配置块全解析与示例 摘要: 本文深入探讨了 Nginx 中 location 配置块的功能、语法规则以及多种实际应用场景下的配置示例,旨在帮助读者全面理解并熟练掌握 location 配置块,以便在 Nginx 服务器配置中灵活运用,实…...
javalock(八)ReentrantReadWriteLock
ReentrantReadWriteLock: 同时实现了共享锁和排它锁。内部有一个sync,同时实现了tryAcquire/tryReleases、tryAcquireShared/tryReleasesShared,一共四个函数,然后ReentrantReadWriteLock内部还实现了一个ReadLock和一个WriteLock,…...
反射和设计模式
一、反射 1. 相关概念 (1) 类的对象:基于定义好的一个类,创建该类的实例,即利用 new 创建的实例就为类的对象。 (2) 类对象:类加载的产物,封装了一个类的所有信息 ( 包名、类名、父类、接口、属性、方法、构造方…...
双指针---和为s的两个数字
这里写自定义目录标题 题目链接问题分析代码解决执行用时 题目链接 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。 问题分析 暴⼒解法,会超时 (两层…...
LLaMA-Factory 单卡3080*2 deepspeed zero3 微调Qwen2.5-7B-Instruct
环境安装 git clone https://gitcode.com/gh_mirrors/ll/LLaMA-Factory.git 下载模型 pip install modelscope modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /root/autodl-tmp/models/Qwen/Qwen2.5-7B-Instruct 微调 llamafactory-cli train \--st…...
智慧农业云平台与水肥一体化:道品科技引领农业现代化新潮流
在当今科技飞速发展的时代,农业也正经历着一场深刻的变革。智慧农业云平台和水肥一体化技术的出现,为农业生产带来了前所未有的机遇和挑战。 一、智慧农业云平台:农业生产的 “智慧大脑” 智慧农业云平台就像是农业生产的 “智慧大脑”&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
