资源 DLL 是使用不同语言资源的有效方法。应用程序可以提供单个 DLL,该 DLL 通过应用程序的设置程序对资源进行了本地化。只要使用正确的 DLL,便很容易更改为其他语言。
以下信息讨论了如何用 Visual C++ 5.0 编写本地化资源 DLL。
本文介绍了一种简单、通用的方法,来生成应用程序以及能支持多种语言的资源 DLL。您可以使用此方法将所有资源集中在一个 RC 文件中,这样一来,要查看已实现的资源便相当容易。
- 创建默认的 MFC AppWizard 应用程序(在本例中称为“MyApp”),然后指定美国英语作为资源语言。使用 MFC 库作为“共享 DLL”。
- 插入默认的 MFC AppWizard DLL 作为顶级项目(在本例中为“ResourceDll”),然后选择“MFC 扩展 DLL(使用共享 MFC DLL)”作为 DLL 的类型。因为没有为 DLL 创建 .lib 文件,所以在后面生成可执行文件过程中,顶级项目不会出现链接器问题。
- 从 ResourceDll 项目中删除 RC 文件、Resource.h 文件、ResourceDll.rc2 文件和 RES 目录。
- 在“项目”菜单中,选择“添加到项目”弹出菜单,然后选择“文件”。将 MyApp.RC 文件插入 ResourceDll 项目中。
- 针对 MyApp 将具有本地化资源的其他每种语言,执行以下操作:
- 在“生成”菜单中,单击“配置”,然后添加新的发布和调试配置。例如,添加“法语发布”配置,并从“ResourceDll - Win32 发布”中复制其设置,然后添加“法语调试”配置,并从“ResourceDll - Win32 调试”中复制其设置。
- 在“项目设置”对话框中,在“设置”组合框中选择“多重配置”。在“选择要修改的项目配置”对话框中,为特定语言选择发布和调试项目配置。在“资源”选项卡上,添加预处理器定义 AFX_RESOURCE_DLL 和 AFX_TARG_XXX,其中 XXX 是语言的字母说明符。例如,FRA 表示法国法语,DEU 表示德语,ENU 表示美国英语。
注意:预处理器定义用逗号分隔,定义之间没有空格。
- 在“语言”组合框中,选择资源所用的语言。
注意:您可能需要为 DLL 命名以便于标识。例如,您可能需要在根名称上添加“d”,以将其标记为调试 DLL,并使用特定于语言的文件扩展名来表明区域设置。请注意,可执行文件的调试版本不会与资源 DLL 的发布版本一同使用。
这可以通过更改链接器用于生成每个 DLL 的输出目标来实现。
- 在“项目设置”对话框中选择“链接”属性页。
- 在“设置”组合框中,突出显示要为其更改 DLL 输出目录的配置。
- 确保“类别”设置为“常规”,并在“输出文件名”下的编辑框中指定输出目录的名称。
以包含法语本地化资源的 DLL 为例,对于 Win32 调试配置,将“Debug/ResourceDLL.dll”更改为“French Debug/ ResourceDLLd.FRA”,对于 Win32 发布配置,将“Release/ResourceDLL.dll”更改为“French Release/ ResourceDLL.FRA”。
要使用这些 DLL,必须将所需的 DLL 复制到 MyApp.exe 所在的目录中或相应的 Windows 目录中,然后将其重命名为 ResourceDll.dll 或 ResourceDllD.dll。例如:
copy ResourceDll.FRA\windows\system\ResourceDll.dll
还可以指定为每个本地化 DLL 生成资源文件 MyApp.res 的目录。
- 在“项目设置”对话框中选择“资源”属性页。
- 在“设置”组合框中,突出显示要为其更改资源输出目录的配置。
- 确保“类别”设置为“常规”,并在“资源文件名”下的编辑框中指定将生成资源输出文件的目录。
- 在“项目”菜单中,选择“设置”并突出显示“ResourceDLL”项目。从“设置”组合框中选择“所有配置”。单击后跟“预处理器”类别的“C/C++”选项卡。在“附加包含目录”字段中添加 MyApp 项目的路径。
- 在“项目”菜单中,选择“设置”并突出显示“MyApp”项目。从“设置”组合框中选择“所有配置”。单击“资源”选项卡,然后在“预处理器定义”字段中,添加 AFX_RESOURCE_DLL。此定义将从 MyApp.exe 中删除所有资源。
- 在 ResourceView 工作区中,打开每个文件夹,然后按住 Ctrl 键,选择 MyApp 项目中的所有资源。例如,您的选择中应当包括用于加速器的 IDR_MAINFRAME 和用于对话框的 IDD_ABOUTBOX。
对于每项 ResourceDLL 配置,在“插入”菜单上,单击“资源副本”,将语言设置为适当的语言,然后按“确定”。现在,您应当具有了另一种语言的完整资源集。不过,还必须对资源进行翻译。
(如果要为其创建本地化资源的语言不在语言列表中,请选择其他语言,然后手动编辑资源文件的文本。进行适当更改之后,资源旁边的括号将显示“未知语言”,并显示语言和子语言标识符。)
注意:您同时还可以将以前存在的资源复制到资源文件中。例如,使用创建初始 MyApp 项目所用的相同选择,创建一个使用法语资源的单独的 MFC AppWizard 应用程序项目。创建此应用程序之后,关闭其工作区,然后打开 MyApp 项目工作区并选择“ResourceView”。然后,在“文件”菜单上,单击“打开”,然后打开法语应用程序的 RC 文件。现在,将法语应用程序的所有资源拖放到 MyApp 应用程序中。这些资源已经是法语的,无需翻译。
- 向应用程序的 CWinApp 派生类中添加一个 HINSTANCE 成员变量。这将保留 DLL 实例句柄。例如:
在项目的 CWinApp::InitInstance 定义中,在函数开头添加以下三行代码:
#ifdef _DEBUG
// Load the debug version of the localized resources.
m_hInstResDLL = LoadLibrary("ResourceDlld.dll");
#else
// Load the release version of the localized resources.
m_hInstResDLL = LoadLibrary("ResourceDll.dll");
#endif
ASSERT( m_hInstResDLL != NULL );
注意:此时无需调用 AfxSetResourceHandle()。
- 使用类向导添加 CMyApp::ExitInstance() 成员函数。添加在应用程序退出之前释放库的代码。按如下所示修改函数:
int CMyApp::ExitInstance()
{
// In case you load multiple DLL's make sure to free them,
// and avoid calling FreeLibrary with a NULL pointer.
FreeLibrary(m_hInstResDLL);
return CWinApp::ExitInstance();
}
- 应用程序即可生成。使用“批生成”对话框,选择所需的目标。请记住,必须将适当的 DLL 复制到合适的位置并重命名。