许多细心的人也许已经注意到,在VC的集成编译环境 (IDE)中有一个功能,你可以选中一个资源,在上面点击鼠标右键,选择Insert Copy,选择一个不同的Condition。然而我用VC十多年,一直没有用过这个特性,也从来不知道他是干吗的。前两天有个网友问我这个东西是干吗的,才下决心去研究一下。仔细研究之后,才发现他是用于资源DLL的。
对于提供国际化解决方案的程序设计者而言,根据用户地区设置来显示对应的语言界面,将是非常有意义的。本文的目的是提供一个step by step的建议,让没有做过资源dll的人可以从中受益。由于我也没做过资源dll,研究这个也就半天时间,因此如果有什么错误,也很正常。请发现错误的朋友直接发邮件给我。对于你的帮助,我将非常感谢。
主工程的要求
对于一个需要使用资源dll实现国际化的工程,我们必须保证每个展现给用户的界面元素都必须从资源里获得。这主要指得是名目繁多的字符串。程序设计者喜欢用AfxMessageBox显示信息。在单语言情况下,这当然没有问题。但是如果是多语言环境,这样做就很难控制这个显示信息和当前的区域设置匹配。
另外,主工程的设计应该在创建资源dll之前完成。这样做的原因是,资源dll设计很简单,花不了多少时间。而如果资源的修改,如果没有正确反映到代码上,有时候程序会莫名其妙的崩溃了,而你需要花很长的时间来找到原因。我自己的一个例子是:我在icon中插入了一个65535色的图片,程序一直起不来,后来找了很久才找到原因。如果我们按照普通方式设计主工程,并经过测试证明他工作正常,此时再做资源dll,就会避免在两个工程之间调试并找原因。
实际上对于增量开发情况,这种资源dll和主工程并存的情况可能难以避免,这时就需要增删资源特别小心,避免导致错误。
为了简化起见,我创建一个缺省的对话框工程来做测试,步骤如下:
- 启动Microsoft Visual Studio 6.0
- 点击File, New
- 选择Microsoft AppWizard(exe)工程,输入工程名test,点击OK
- 选择Dialog Based,并在What language would you like your resources in?下选择中文(此时选择自己最喜欢的语言即可,我不熟悉英文,就选择中文了)
- 点击Finish创建工程
创建资源dll工程
我们可以按照下述步骤创建一个资源DLL:
- 创建一个普通的WIN32 Dynamic-Link Library(这里取名testdll)
- 把主工程中的所有资源相关的文件(rc,rc2,ico等)加入这个dll工程
- 点击菜单Build, Configurations,此时,我们应该有Release和Debug两个配置
- 点击Add按钮,以Debug为模板创建DebugEN和DebugCN
- 重复上述步骤,以Release为模板,创建ReleaseEN和ReleaseCN
- 删除原来的Debug和Release配置,然后点击Close退出配置对话框
- 按组合键ALT+F7弹出Project Settings对话框
- 选择Resources页
- 左侧选择All Configurations
- 在Preprocessor Definitions中添加如下宏AFX_RESOURCE_DLL
- 左侧选择Multiple Configurations,选中DebugEN和ReleaseEN
- 重复第10步,输入AFX_TARG_ENU宏(这是为美国英语而定义的宏English U.S)
- 重复11,12步,为DebugCN和ReleaseCN添加AFX_TARG_CHS宏(这是为简体中文的宏Chinese Simplified)
- 选择Link页,为每个配置指定输出文件名(我这里分别为testdll_end.dll, testdll_enr.dll, testdll_cnd.dll,testdll_cnr.dll,分别表示英文debug,英文release和中文相关文件)
- 关闭Project Settings对话框
- 选中Resource View
- 在每个资源ID上右击,选择Insert Copy,改变Language为English(U.S)
- 如果为同一种语言你还希望提供根据某个自定义的宏而选择不同的界面(如UI模式和Service模式),在Condition中输入你用以区分的宏名,如SERVICE_DLL。
- 打开每个新创建的资源,根据自己的需要修改资源(注意:这里只建议修改文字、字体,必须严格保证不删除任何资源)
- 保存修改
- 编译资源DLL
修改主工程
由于我们打算用资源dll来提供资源信息,我们必须对主工程做如下修改:
- 打开工程
- 选择File View,删除rc,rc2,ico等和资源密切相关的文件。resource.h请不要删除
- 在CWinApp中添加一个私有的HMODULE类型的变量m_hResource
- 在InitInstance函数开头添加如下代码:
LANGID id = ::GetUserDefaultLangID(); switch(id) { case 0x804://中文 #ifdef _DEBUG m_hResource = LoadLibrary(_T("D:\\projects\\testdll\\DebugCN\\testdllcnd.dll")); #else m_hResource = LoadLibrary(_T("D:\\projects\\testdll\\ReleaseCN\\testdllcnr.dll")); #endif break; default: #ifdef _DEBUG m_hResource = LoadLibrary(_T("D:\\projects\\testdll\\DebugEN\\testdllend.dll")); #else m_hResource = LoadLibrary(_T("D:\\projects\\testdll\\ReleaseCN\\testdllenr.dll")); #endif } if(m_hResource == NULL) { return FALSE; }else{ AfxSetResourceHandle((HINSTANCE)m_hResource); }
此后再做一点简单的调试,应该就可以了。具体调试,就已经超出我这篇文章所能讨论的范围了。
|