MFC多国语言——资源副本
此随笔主要参考了http://www.cnblogs.com/xianyunhe/archive/2011/09/02/2163842.html
为软件提供多国语言的支持的具体实现方法有很多,但基本原理都差不多,就是实现代码和语言包的独立,代码根据设定的语言选择语言包。
其中,MFC的资源文件就提供了对多国不同语言的支持功能,如果使用MFC开发,直接用资源文件自带的多国语言支持,可以省去不少的麻烦。
下面就介绍给MFC程序添加中英文的支持,开发环境为VS2010。
1. 新建工程
新建了一个对话框工程,工程名称为MultiLanguages,默认语言选择是“中文”。
2. 添加多国语言的资源
在创建工程后,工程会添加默认的资源,如主对话框,都是“中文”资源。现在我们需要添加相应的英文的资源文件。
为主窗口IDD_MULTILANGUAGES添加英文资源的方法为:
(1) 打开Resource View窗口。
(2) 右键IDD_MULTILANGUAGES,点击弹出菜单中的“Insert Copy”菜单。
(3) 弹出窗口资源复制语言选择窗口,选择语言为“英语(美国)”。
(4) 点击OK,即完成英文版对话框的添加。完成添加后,IDD_MULTILANGUAGES就对应于两个不同语言版本的对话框了。
使用同样的方法,也可以为其他资源添加多国语言版本的支持。主要需要多国版本需要支持的有对话框、菜单和字符串。
添加多国语言的资源后,要对这些资源进行不同语言的定制,根据资源对应的语言,设置对话框和控件的标题等。
3. Locale
程序的语言选择跟操作系统语言(System Locale)、用户设置语言(User Locale)和线程语言(Thread Locale)有关。程序运行时,是根据线程语言来选择资源的。如果程序中未对线程语言进行设置,线程语言默认采用用户设置语言。设置线程语言的函数是SetThreadLocale。
设置线程语言为“中文”的代码如下:
SetThreadLocale(MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT));
设置线程语言为“英语(美国)”的代码如下:
SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
设置线程语言要在对话框创建之前,否则无法更改对话框的资源。可以在CMultiLanguagesApp::InitInstance函数中的对话框初始化之前添加线程语言设置,分别设置为中文和英文语言,就可以查看到对话框界面的不同。
4. 字符串处理
程序的多国语言的支持,不仅包括界面的多国语言支持,也要包括各类字符串的多国语言支持,如弹出的提示信息。因此,在弹出提示信息时,也要为提示信息创建多个语言版本,并根据当前线程的语言来选择不同的提示信息。
例子:实现不同语言版本中按钮的点击次数的统计。
(1) 在String Table中分别添加中英文的IDS_STRING_SAMPLE资源,内容如下表所示。
中文 |
这个一个中文提示信息。\n点击次数:%d。 |
英文 |
This is a prompt message in English.\nClick Times:%d. |
(2) 在主窗口控件中添加一个控件Button1,控件的中文名为“提示”,英文名称为“Prompt”。为该控件添加一个左键单击消息响应函数,该函数的内容如下:
void CMultiLanguagesDlg::OnBnClickedButton1() { // TODO: Add your control notification handler code here static int s_iClickTime = ; s_iClickTime++; CString strPrompt = _T(""); CString strFormat = _T(""); strFormat.LoadString(IDS_STRING_SAMPLE); strPrompt.Format(strFormat, s_iClickTime); AfxMessageBox(strPrompt); }
(3) 分别在CMultiLanguagesApp::InitInstance添加设置线程语言为中文和英文的代码,然后多次点击按钮进行测试。
5. 语言切换
窗口在初始化时候就导入了资源文件,在通过SetThreadLocale更换了线程语言后,窗口的资源并不会更改,必须要通过代码来重新装载资源。因为窗口中存在多种与线程语言相关的资源,重新启动软件一种叫快捷的更新语言环境的方法。
例:通过菜单来进行语言切换,切换语言后重启软件。
(1) 为程序添加中英文菜单选项ID_LANGUAGE_SWITCH,并为该菜单添加消息响应函数,其中,m_bRestartFlag使用判断关闭窗口时是否需要重启程序的标识。代码如下。
void CMultiLanguagesDlg::OnLanguageSwitch() { // TODO: Add your command handler code here // 读取当前线程的语言,并根据当前线程语言进行语言切换 LCID lcidNew = GetThreadLocale(); if (LANG_ENGLISH == PRIMARYLANGID(LANGIDFROMLCID(lcidNew))) { lcidNew = MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT); } else { lcidNew = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); } // 把语言设置写入配置文件 CFile file; file.Open(_T("Language.ini"), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary); file.Write(&lcidNew, sizeof(lcidNew)); file.Close(); // 关闭窗口 m_bRestartFlag = TRUE; PostMessage(WM_CLOSE, , ); }
(2) 在关闭窗口时,重启动该程序。即在窗口响应WM_CLOSE时,重启程序。代码如下:
void CMultiLanguagesDlg::OnClose() { // TODO: Add your message handler code here and/or call default // 判断是否需要重新启动窗口 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(); }
(3) 在启动软件时,根据当前软件的配置文件中语言来设置线程语言,即在CMultiLanguagesApp::InitInstance函数中创建对话框之前设置线程语言,代码如下:
// 判断你是否存在配置文件,如果存在,从配置文件中读取语言设置 CString strFileName = _T("Language.ini"); if (PathFileExists(strFileName)) { LCID lcidThread = ; CFile file; file.Open(strFileName, CFile::modeRead | CFile::typeBinary); file.Read(&lcidThread, sizeof(LCID)); file.Close(); SetThreadLocale(lcidThread); }
(4) 通过点击菜单来测试软件的语言切换。
6. MessageBox的问题
由于MessageBox中的按钮的语言是跟操作系统相关的,要想实现MessageBox按钮的多语言化是很有一定难度的。我现在还没有查到好的解决方法,很多网友的建议是抛弃MessageBox,自己建立对话框。
7. 相关函数和类型
与本地化相关的函数和类型如下:
GetSystemDefaultLCID
GetSystemDefaultLocaleName
GetUserDefaultLCID
GetUserDefaultLocaleName
SetThreadLocale
GetThreadLocale
MAKELCID
MAKELANGID
LCIDToLocalName
LocalNameToLCID
LANGIDFROMLCID
PRIMARYLANGID
LCID
LANGID
LANG_CHINESE 0x04
LANG_ENGLISH 0x09
8. 相关问题
如果在控制面板“区域和语言”设置中,设置“区域选项”为“英文(美国)”,调用SetThreadLocale设置区域语言为英文不起作用,界面仍然显示中文。
从网上找到别人提出的分析:
代码运行原理:
1)SetThreadLocale函数内部会判断设置的语言是否与当前语言(就是你在区域设置里面设置的语言)一致。
2)如果一致,则不做具体操作,否则修改LocaleInfo信息,并记录语言做了修改操作。
3)FindResoucesEx在实现上首先判断LocaleInfo是否修改过,如果修改过则取修改设置的语言字符串;如果没有修改则直接取系统默认语言(是操作系统自身的语言,不是区域设置里面设置的语言)。由于你在区域里设置了设置了语言为英文(美国),当你的程序SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US))后,系统认为你设置的语言与当前语言一致,没有置修改标志。而当你LoadString时则直接取系统语言中文来加载字符串啦。
我测试了,如果在资源里添加“英文(英国)”语言资源,此时在系统区域里设置为“英文(美国)”,SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_UK))后可以加载英文(英国)的语言资源。
MFC多国语言——资源副本的更多相关文章
- MFC多国语言——资源DLL
此随笔中主要内容来自http://blog.csdn.net/china_hxx/article/details/10066655,原出处不详. 以下内容基于VC 6.0.要实现界面多语言化,必须要先 ...
- MFC多国语言——配置文件
前段时间,因工作需要,本地化了一个英文版本的产品. 在网上查阅了若干资料,在此进行一个简单的整理. 在MFC程序中,实现多国语言的方式很多,我们选择的是使用配置文件的方法. 在通过配置文件方式实现多国 ...
- 高质量,高效率的多国语言软件开发(Web/PC/Mobile),使用接口约束/调用不同语言资源
偶然间翻出了几年前写的一个小程序,把当时的资料整理整理分享一下. 当时为了给自己的软件实现多国语言功能,而开发的辅助工具:SE String Resource. 这是当时基于自己另一款 IDE 软件抽 ...
- 解析大型.NET ERP系统 多国语言实现
实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...
- WinCE6.0多国语言软键盘
N久以前写过一篇<WinCE下自定义的大软键盘>,这个自定义软键盘就是为RM905a+项目来做的.RM905a+的系统分辨率是640*480,WinCE原生键盘小的太小,大的又太大.所以就 ...
- 引擎设计跟踪(九.8) Gizmo helper实现与多国语言
最近把gizmo helper的绘制做好了. 1.为了复用代码,写了utility来创建sphere, cube, cylinder, plane, ring(line), circle(solid) ...
- C#实现多国语言的界面切换
在PictureStudio中,我需要实现多国语言的界面切换,而且切换各种语言版本的时候希望程序是动态的加载语言,不希望切换语言后重新启动程序. 实现这样的功能可以有很愚蠢的方法,比如说你可以在程序中 ...
- [Windows Phone] 以多国语言做为开发前提 (1)
原文:[Windows Phone] 以多国语言做为开发前提 (1) ? 前言 在先前 TechDays 2013 的课程 [开发 Windows Phone 商务应用程式就是这麽快] 中,其中一个部 ...
- [Windows Phone] 以多国语言做为开发前提 (2)
原文:[Windows Phone] 以多国语言做为开发前提 (2) ? 前言 在先前的文章 [Windows Phone 开发 - 以多国语言做为开发前提 (1)] 中说明了简单的多国语言范例,今天 ...
随机推荐
- kindeditor 图片上传插件
富文本编辑器,kindeditor是比较好用的一款.需要的功能都有,文档.demo也详细.有什么功能去官网看一眼就好. 官网:http://kindeditor.net/ 一些好用的如图片上传,kin ...
- 在UNC(通用命名规范)路径和URL中使用IPv6地址
转自:http://www.ipv6bbs.cn/thread-348-1-1.html 虽然微软在支持IPv6上表现得很积极,但Windows却并没有完整地支持IPv6,例如,在Windows中 ...
- 设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)
什么是简单工厂模式? 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式.通过专门定义一个类来负责创建其它类的实例,被创建的实例 ...
- jConsole,jvisualvm和jmap使用
JConsole JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.可以轻松地使用 JConsole来监控 Java 应用程序性能和跟踪 Jav ...
- Latex插入项目列表符号
1. 关于 {itemize}里序号的形式 (这个在书里有介绍): latex默认生成的简单列表, 默认为一个小圆点,..... 而我们在写文章时可能想要一些不一样的列表符号, 比如 -, * 之类的 ...
- bootstrap学习笔记 多媒体对象
本文将介绍Bootstrap中的多媒体对象(Media Object).这些抽象的对象样式用于创建各种类型的组件(比如博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐.媒体对象可以用 ...
- 微信小程序 异步请求拿数据+使用外部js库
信小程序(与js)通过requirejs引用外部js文件 var modelSearch = require('../../utils/modelSearch.js') 这是一个构建数据请求筛选条件的 ...
- 关于cnblogs的排版
cnblogs默认的样式实在让我无法接受.今天去看了看div+css的基本知识. 决定这周抄一个别人的排版,稍微改改. 不然,就这样式,实在没心情写博客. 写博客,这次准备要大干一场了.
- 纯CSS3实现一个旋转的3D立方体盒子
简单介绍 上网易前端微专业课程,里面有一个课外作业是实现一个3D旋转立方体.花了点时间做了下.还有点意思.写个简单教程.供大家学习. 先放上终于要实现的效果 注:代码在chrome 43.0.2357 ...
- U3D Debug.DrawRay
Debug.DrawRay第二个参数方向,事实上需要手动输入长度.并且不是无限长的射线,是根据方向的长度来的 如果参数不指定颜色,绘制出来的就是白色