在当今这个发展越来越快的世界中,软件的本地化及翻译工作越来越重要,极大地关系到软件的销量及普及率;就拿常见的Win32/MFC
程序来说,一个比较方便的办法就是附加单独的资源DLL文件。
本文介绍了一种易于应用的方法,可在C++/MFC程序中支持多种语言,并演示了怎样用少量的代码添加对资源DLL的支持,这包含了两个方面:根据用户偏好在程序开始时自动选择最合适的语言;提供一个语言选择子菜单(以供用户自行选择)。
关于资源DLL
有关在程序中支持多语言最灵活的方法,也许就是使用所谓的“资源DLL”了,其主要思想是为每种语言创建一个单独的DLL文件,而这个DLL中包含了已翻译为某种特定语言的程序资源;因此,如果你的程序最初版本是中文,且又翻译成了法文、德文、日文,这样你就有了三个资源DLL。中文资源在.exe文件中,而其他三种语言各自对应一个DLL文件。
如果程序中又需要支持某种新的语言,只须简单地添加一个DLL到安装文件中就行了。在程序运行时,会根据用户偏好,相应地加载资源DLL。
资源DLL可由一个专门的Visual Studio工程来创建,也可由某些专用的工具来创建,本文以Visual Studio 2003来创建,Visual Studio 2005也差不多。顺便提一下,把所有的语言资源都打包进EXE文件,在理论上是可行的,但在实际中却行不通;因为,大多数加载资源的高层API——如LoadString()、DialogBox()等等——不会让你指定想要的语言,而SetThreadLocale()也不会如预期那样工作(此API在Win9X中不存在)。
一步一步支持资源DLL
以下是在主程序中,添加支持资源DLL(语言选择菜单)的步骤:
1、 把LanguageSupport.h及LanguageSupport.cpp添加到你的工程。
在MyApp.h及MyApp.cpp(假定CMyApp是工程类)中,加入以下黑体行:
以下是引用片段: #include "LanguageSupport.h" class CMyApp : public CWinApp { public: CLanguageSupport m_LanguageSupport; ... }; BOOL CMyApp::InitInstance() { //把以下这行注释掉,防止MFC进行自己的资源DLL处理。 // CWinApp::InitInstance(); ... SetRegistryKey(_T("MyCompany")); //根据用户偏好,加载相应的资源DLL。 m_LanguageSupport.LoadBestLanguage(); ... } |
在主菜单中,添加一个名为“语言(Language)”的菜单项。接下来,在CMainFrame类中,为“语言(Language)”菜单项添加一个菜单更新处理程序,假定名为OnUpdateToolsLanguage(),如下所示:
以下是引用片段: void CMainFrame::OnUpdateToolsLanguage(CCmdUI *pCmdUI) { //创建语言子菜单(只在菜单第一次打开时)。 theApp.m_LanguageSupport.CreateMenu(pCmdUI); } |
2、 为语言选择菜单项添加菜单处理程序。
在MainFrm.h中,把处理程序afx_msg void OnLanguage(UINT nID)添加在CMainFrame的protected部分中某处;在MainFrm.cpp中,添加定义及消息映射入口:
以下是引用片段: BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ... ON_COMMAND_RANGE(ID_LANGUAGE_FIRST,ID_LANGUAGE_LAST, OnLanguage) //这些ID声明在LanguageSupport.h中 END_MESSAGE_MAP() void CMainFrame::OnLanguage(UINT nID) { //用户选择了菜单中的某种语言 theApp.m_LanguageSupport.OnSwitchLanguage(nID); } |
注意,这个处理程序不能用向导来添加,因为它是一个COMMAND_RANGE菜单处理程序——用于处理“语言(Language)”菜单中所有语言项。
3、 也是最后一步,在字符资源表中,添加一个名为IDS_RESTART的字符串,值为“请重新运行%1”,%1可为程序名。
怎样创建资源DLL
首先,CLanguageSupport类假定所有的DLL都名为MyAppXXX.dll,这里MyApp.exe是可执行文件名,XXX是所支持语言的三个字母缩写(CHN代表中文、FRA代表法文、DEU代表德文、JPN代表日文)。同时,exe文件与dll文件都应有一个Version版本信息资源,其语言匹配文件名中的三个缩写字母。接着,我们创建一个Win32 DLL工程:
1、 打开Visual Studio 2003,选择文件-新建-工程,输入工程名如MyAppDEU创建一个德文版本,单击确定;在程序设置页,选择DLL及空项目。
2、 把它转换为一个资源DLL:打开项目属性,在“配置”下拉框中选择“所有配置”;打开链接器-高级,将“纯资源DLL”设为“是”。另外,如果你使用Visual C++ 6.0,则需要手工在链接设置的编辑框中添加 /NOENTRY作为命令行选项;而Visual C++ 2005,与Visual C++ 2003类似,在链接器-高级里,选择“无入口点”为“是”。
3、 创建一份EXE资源文件的副本,并把它添加到DLL工程中:建议将MyApp.rc文件改名成所需的语言版本,如MyAppDEU.rc。
4、 修改路径:在资源视图中,鼠标右键单击MyAppDEU.rc,打开“资源包含”,修改所有包含资源文件的路径。每种语言都有会一个子目录l.xxx,例如,修改#include "afxres.rc"为#include "l.deu\afxres.rc"。
5、 设置语言属性:在资源视图中,打开“版本信息version info”(如果没有就创建一个),设置语言属性为正确的语言,如German(Germany),确保语言匹配DLL名中的三个字母。
现在可以编译DLL了,之后便可得到一个资源DLL,当然,它还没有经过翻译,但这已是翻译者的任务了。按照上述步骤就可创建出一系统语言的DLL,你唯一要做的事情,就是把它们复制到应用程序的目录了。另外,从程序中加载资源DLL也非常简单,LoadLibrary()与AfxSetResourceHandle(hDll)就可以胜任了。
以下是源代码:
以下是引用片段: LanguageSupport.h #pragma once #include #define ID_LANGUAGE_FIRST 0x6F00 #define ID_LANGUAGE_LAST 0x6FFF class CLanguageSupport { public: CLanguageSupport(); ~CLanguageSupport(); void CreateMenu(CCmdUI *pCmdUI, UINT nFirstItemId= ID_LANGUAGE_FIRST); void OnSwitchLanguage(UINT nId, bool bLoadNewLanguageImmediately= false); void LoadBestLanguage(); protected: CWordArray m_aLanguages; LANGID m_nExeLanguage; LANGID m_nCurrentLanguage; HINSTANCE m_hDll; static const TCHAR szLanguageId[]; static LANGID GetLangIdFromFile(LPCTSTR pszFilename); static CString GetLanguageName(LANGID wLangId); static LANGID GetUserUILanguage(); static LANGID GetSystemUILanguage(); void GetAvailableLanguages(); bool LoadLanguage(); bool LoadLanguageDll(); void LookupExeLanguage(); void UnloadResourceDll(); static void SetResourceHandle(HINSTANCE hDll); }; LanguageSupport.cpp #include "stdafx.h" #include
阅读(206)
(责任编辑:城市网)
|