此随笔中主要内容来自http://blog.csdn.net/china_hxx/article/details/10066655,原出处不详。

以下内容基于VC 6.0。要实现界面多语言化,必须要先配置项目使其支持Unicode编码,文章《VC下的Unicode编程》 对此有详细介绍。

首先创建一个基于MFC的工程,在选择语言时选择 中文[简体,中国]。

项目框架选择对话框、单文档和多文档都可以,这里就选个基于对话框的吧,然后立即修该项目属性使其支持Unicode。

MFC已经为我们加入了一些资源,包括2个对话框、1个String Table等。为了节省空间修改了对话框的大小。

现在项目中的资源情况如下:

然后再新建一个DLL项目,为了方便管理可以将其添加到当前工作空间中。

立即修改此DLL项目使其支持Unicode,然后设置项目依赖性(Project->Dependencies…) ,资源DLL要在exe项目之前编译:

为了将生成的资源DLL自动拷贝到exe项目执行目录下,还需要修改DLL项目的Post-build Step:

然后将主项目目录下的res文件夹、resource.h、TestMultiLang.rc文件拷贝到ResENG项目目录下,res文件夹和resource.h直接替换,将ResENG.rc删除后再将TestMultiLang.rc重命名为ResENG.rc。

切换到资源视图就会发现这两个项目的资源内容是一样的了,将ResENG项目的资源更改为英文如下:

为了让程序在启动的时候加载英文语言资源,需要在CTestMultiLangApp::InitInstance()函数中Dlg创建之前添加如下语句:

HINSTANCE hLanguageDll = AfxLoadLibrary(_T("ResENG")); if (hLanguageDll) AfxSetResourceHandle(hLanguageDll);

最后重新编译TestMultiLang项目,运行就会发现对话框已经是英文界面了 :)

动态实现语言切换

以上程序仅为示例,为了能使程序自动选择合适的语言,还需要做许多工作。比如要在程序中添加程序语言切换菜单或语言选择下拉列表框,并将用户喜好保存在ini配置文件中,然后在程序启动时自动读取此ini文件加载相应的资源DLL;如果用户未设置语言,则默认根据操作系统语言加载合适资源,如果不存在针对此语言的资源DLL,就使用最国际化的语言——英语。

在stdafx.h中做如下定义:

#define CHINESE    0
#define ENGLISH 1

在CTestMultiLangApp类中添加private变量 int m_Lang, 用来保存当前语言类型是CHINESE,还是ENGLISH。

在CTestMultiLangApp类中添加public方法GetLang用于返回当前语言类型。

int CTestMultiLangApp::GetLang(void)
{
return m_Lang;
}

根据配置加载相应资源的DLL包装成一个函数如下:

void CTestMultiLangApp::LoadLanguage(void)
{
CString strDLL;
HINSTANCE hLanguageDll, hLanguageNow; //保存本身的资源句柄
static HINSTANCE hOriginalHandle = ::AfxGetResourceHandle(); //读取ini配置文件
CString strFileName = _T("Language.ini");
if (PathFileExists(strFileName))
{
int lang = ;
CFile file;
file.Open(strFileName, CFile::modeRead | CFile::typeBinary);
file.Read(&lang, sizeof(lang));
file.Close();
m_Lang = lang;
} //根据用户喜好来设置
if (m_Lang == ENGLISH)//英文
hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
else if (m_Lang == CHINESE)//中文
hLanguageDll = hOriginalHandle;
else
{
//用户未指定,则根据系统选择合适语言,默认为英文
WORD wLangPID = PRIMARYLANGID(GetSystemDefaultLangID());
if (wLangPID == LANG_CHINESE)
hLanguageDll = hOriginalHandle;
else if (wLangPID == LANG_ENGLISH)
hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
else
hLanguageDll = ::AfxLoadLibrary(_T("ResENG"));
}
//保存已加载的资源DLL句柄
hLanguageNow = ::AfxGetResourceHandle();
//加载新的资源DLL
if(hLanguageDll)
::AfxSetResourceHandle(hLanguageDll);
//释放之前加载的资源DLL
if (hLanguageNow != hOriginalHandle)
FreeLibrary(hLanguageNow);
}

因为在切换界面语言的过程中需要频繁地销毁和创建对话框,所以我们也把创建对话框的代码包装成一个函数:

void CTestMultiLangApp::OpenWindow(void)
{
CTestMultiLangDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
}

现在在InitInstance()函数里简单得调用一下这两个函数就可以了:

BOOL CTestMultiLangApp::InitInstance()
{
AfxEnableControlContainer(); #ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif LoadLanguage(); if (!OpenWindow())
return FALSE; return FALSE;
}

然后要实现用户界面的语言选择消息响应函数。该函数要将用户的选择保存到ini文件里,销毁当前窗口,然后再重新加载资源并创建新的窗口:

void CTestMultiLangDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CTestMultiLangApp*pApp = (CTestMultiLangApp*)AfxGetApp(); int old_Lang = pApp->GetLang();
int new_Lang = ;
if(old_Lang == ENGLISH)
new_Lang = CHINESE;
else
new_Lang = ENGLISH; CFile file;
file.Open(_T("Language.ini"), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary);
file.Write(&new_Lang, sizeof(new_Lang));
file.Close(); //销毁当前窗口
pApp->m_pMainWnd = NULL;
this->DestroyWindow(); //创建新的窗口
pApp->LoadLanguage();
pApp->OpenWindow();
}

上面这段代码中pApp->m_pMainWnd = NULL这一句是关键,它切断了销毁当前程序消息向上的路由,因此进程不会被销毁,才有了机会重新创建新的窗口。如果项目是基于单文档/多文档的程序的话,还要加一句pApp->m_pDocManager = NULL才可以。
    重新编译项目,现在语言就可以动态切换了。

继续添加其他语言

如果项目不仅要支持中英文这两种语言,比如还需要支持德语,这里介绍两种方法来实现。

第一种方法显而易见————新建一个资源DLL项目。理论上这是可行的,但是有个棘手的问题:如果需要支持的语言很多,那么对程序资源的任何更改都需要同步更新到其他所有资源项目!
    第二种方法是借用工具,由一个资源DLL制作出其他各语言版本的资源DLL。这个工具软件会把资源DLL中的字符串、对话框、菜单项等资源提取出来并保存到一个po文件里,之后使用poedit就可以进行翻译了。翻译完成后再根据此po文件和原资源DLL生成新的资源DLL。
    工具软件截图如下:

MFC多国语言——资源DLL的更多相关文章

  1. MFC多国语言——资源副本

    此随笔主要参考了http://www.cnblogs.com/xianyunhe/archive/2011/09/02/2163842.html 为软件提供多国语言的支持的具体实现方法有很多,但基本原 ...

  2. MFC多国语言——配置文件

    前段时间,因工作需要,本地化了一个英文版本的产品. 在网上查阅了若干资料,在此进行一个简单的整理. 在MFC程序中,实现多国语言的方式很多,我们选择的是使用配置文件的方法. 在通过配置文件方式实现多国 ...

  3. 高质量,高效率的多国语言软件开发(Web/PC/Mobile),使用接口约束/调用不同语言资源

    偶然间翻出了几年前写的一个小程序,把当时的资料整理整理分享一下. 当时为了给自己的软件实现多国语言功能,而开发的辅助工具:SE String Resource. 这是当时基于自己另一款 IDE 软件抽 ...

  4. WPF应用程序支持多国语言解决方案

    原文:WPF应用程序支持多国语言解决方案 促使程序赢得更多客户的最好.最经济的方法是使之支持多国语言,而不是将潜在的客户群限制为全球近70亿人口中的一小部分.本文介绍四种实现WPF应用程序支持多国语言 ...

  5. Delphi如何实现多国语言

    Delphi里的多语言处理方法都一样, 都是通过资源DLL的形式进行加载处理. Delphi在加载form数据的时候会判断当前的系统语言,然后根据语言加载不同的资源dll, 来实现多国语言的功能. 下 ...

  6. 解析大型.NET ERP系统 多国语言实现

    实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...

  7. WinCE6.0多国语言软键盘

    N久以前写过一篇<WinCE下自定义的大软键盘>,这个自定义软键盘就是为RM905a+项目来做的.RM905a+的系统分辨率是640*480,WinCE原生键盘小的太小,大的又太大.所以就 ...

  8. 引擎设计跟踪(九.8) Gizmo helper实现与多国语言

    最近把gizmo helper的绘制做好了. 1.为了复用代码,写了utility来创建sphere, cube, cylinder, plane, ring(line), circle(solid) ...

  9. 【软件多国语言】一个demo

    之前上学的时候做过一个东西,需要中英文软件界面,并且需要随时可以切换,当时是师妹来做的,用的最直接也是最笨的办法, what? if(中文) { button1.Text = "花姑娘&qu ...

随机推荐

  1. POJ2406-Power Strings(kmp循环节)

    Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 31111   Accepted: 12982 D ...

  2. MySQL中 order by 与 limit 的执行顺序以及使用实例

    在 MySQL 执行查询的时候,我们可能既要对结果集进行排序又要限制行数,那么此时 order by 与 limit 的执行顺序是怎么样的呢? order by与limit的执行顺序是:先执行orde ...

  3. Swift的String与OC的NSString的区别

    Swift的String类型是值类型.如果你创建了一个新的字符串值,那么当其进行常量.变量赋值操作或在函数/方法中传递时,会进行值拷贝. 在不同的情况下,都会对已有字符串值创建新的副本,并对该新副本进 ...

  4. Linux-查看进程的完整路径

    通过ps及top命令查看进程信息时,只能查到相对路径,查不到的进程的详细信息,如绝对路径等.这时,我们需要通过以下的方法来查看进程的详细信息:Linux在启动一个进程时,系统会在/proc下创建一个以 ...

  5. Struts2中的变量

    <package name="mypackage" extends="struts-default"> <global-results> ...

  6. ANSI实现动态 sql

    /* 包含C头文件 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* 包含SQLCA ...

  7. 轻量集群管理工具PSSH

    PSSH 的意思是 Parallel SSH,并行的SSH,很好理解,PSSH 可以让一条命令在多个服务器上同时执行 这就简化了集群的管理工作,例如想查看一下各台服务器现在的负载状况,就可以通过 PS ...

  8. 150. Best Time to Buy and Sell Stock II【medium】

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  9. 配置taglib的uri的2种方法

    推荐方法1 1.把uri写在tld文件中,tld放在WEB-INF文件夹下,例如: <short-name>就对应了你在jsp中引用的时候<%@ taglib prefix=&quo ...

  10. linux学习笔记28--监控命令vmstat,iostat, lsof

    linux的监控包括多个方面,常用的是进程,内存,I/O,磁盘空间这三个方面. vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程. ...