[MSDN] 如何为MFC 应用程序创建本地化资源DLL?

概要

资源 DLL 是使用不同语言资源的有效方法。应用程序可以提供单个 DLL,该 DLL 通过应用程序的设置程序对资源进行了本地化。只要使用正确的 DLL,便很容易更改为其他语言。

以下信息讨论了如何用 Visual C++ 5.0 编写本地化资源 DLL。

回到顶端

更多信息

本文介绍了一种简单、通用的方法,来生成应用程序以及能支持多种语言的资源 DLL。您可以使用此方法将所有资源集中在一个 RC 文件中,这样一来,要查看已实现的资源便相当容易。

1. 创建默认的 MFC AppWizard 应用程序(在本例中称为“MyApp”),然后指定美国英语作为资源语言。使用 MFC 库作为“共享 DLL”。
2. 插入默认的 MFC AppWizard DLL 作为顶级项目(在本例中为“ResourceDll”),然后选择“MFC 扩展 DLL(使用共享 MFC DLL)”作为 DLL 的类型。因为没有为 DLL 创建 .lib 文件,所以在后面生成可执行文件过程中,顶级项目不会出现链接器问题。
3. 从 ResourceDll 项目中删除 RC 文件、Resource.h 文件、ResourceDll.rc2 文件和 RES 目录。
4. 在“项目”菜单中,选择“添加到项目”弹出菜单,然后选择“文件”。将 MyApp.RC 文件插入 ResourceDll 项目中。
5. 针对 MyApp 将具有本地化资源的其他每种语言,执行以下操作:

a. 在“生成”菜单中,单击“配置”,然后添加新的发布和调试配置。例如,添加“法语发布”配置,并从“ResourceDll - Win32 发布”中复制其设置,然后添加“法语调试”配置,并从“ResourceDll - Win32 调试”中复制其设置。
b. 在“项目设置”对话框中,在“设置”组合框中选择“多重配置”。在“选择要修改的项目配置”对话框中,为特定语言选择发布和调试项目配置。在“资源”选项卡上,添加预处理器定义 AFX_RESOURCE_DLL 和 AFX_TARG_XXX,其中 XXX 是语言的字母说明符。例如,FRA 表示法国法语,DEU 表示德语,ENU 表示美国英语。

注意:预处理器定义用逗号分隔,定义之间没有空格。
c. 在“语言”组合框中,选择资源所用的语言。

注意:您可能需要为 DLL 命名以便于标识。例如,您可能需要在根名称上添加“d”,以将其标记为调试 DLL,并使用特定于语言的文件扩展名来表明区域设置。请注意,可执行文件的调试版本不会与资源 DLL 的发布版本一同使用。

这可以通过更改链接器用于生成每个 DLL 的输出目标来实现。

1. 在“项目设置”对话框中选择“链接”属性页。
2. 在“设置”组合框中,突出显示要为其更改 DLL 输出目录的配置。
3. 确保“类别”设置为“常规”,并在“输出文件名”下的编辑框中指定输出目录的名称。
以包含法语本地化资源的 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 的目录。

1. 在“项目设置”对话框中选择“资源”属性页。
2. 在“设置”组合框中,突出显示要为其更改资源输出目录的配置。
3. 确保“类别”设置为“常规”,并在“资源文件名”下的编辑框中指定将生成资源输出文件的目录。
6. 在“项目”菜单中,选择“设置”并突出显示“ResourceDLL”项目。从“设置”组合框中选择“所有配置”。单击后跟“预处理器”类别的“C/C++”选项卡。在“附加包含目录”字段中添加 MyApp 项目的路径。
7. 在“项目”菜单中,选择“设置”并突出显示“MyApp”项目。从“设置”组合框中选择“所有配置”。单击“资源”选项卡,然后在“预处理器定义”字段中,添加 AFX_RESOURCE_DLL。此定义将从 MyApp.exe 中删除所有资源。
8. 在 ResourceView 工作区中,打开每个文件夹,然后按住 Ctrl 键,选择 MyApp 项目中的所有资源。例如,您的选择中应当包括用于加速器的 IDR_MAINFRAME 和用于对话框的 IDD_ABOUTBOX。

对于每项 ResourceDLL 配置,在“插入”菜单上,单击“资源副本”,将语言设置为适当的语言,然后按“确定”。现在,您应当具有了另一种语言的完整资源集。不过,还必须对资源进行翻译。

(如果要为其创建本地化资源的语言不在语言列表中,请选择其他语言,然后手动编辑资源文件的文本。进行适当更改之后,资源旁边的括号将显示“未知语言”,并显示语言和子语言标识符。)

注意:您同时还可以将以前存在的资源复制到资源文件中。例如,使用创建初始 MyApp 项目所用的相同选择,创建一个使用法语资源的单独的 MFC AppWizard 应用程序项目。创建此应用程序之后,关闭其工作区,然后打开 MyApp 项目工作区并选择“ResourceView”。然后,在“文件”菜单上,单击“打开”,然后打开法语应用程序的 RC 文件。现在,将法语应用程序的所有资源拖放到 MyApp 应用程序中。这些资源已经是法语的,无需翻译。
9. 向应用程序的 CWinApp 派生类中添加一个 HINSTANCE 成员变量。这将保留 DLL 实例句柄。例如:
   HINSTANCE m_hInstResDLL;
            


在项目的 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()。
10. 使用类向导添加 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();
            }
            


11. 应用程序即可生成。使用“批生成”对话框,选择所需的目标。请记住,必须将适当的 DLL 复制到合适的位置并重命名。

回到顶端

参考

技术说明 56 (TN056) 阐述了本地化 MFC 资源 (MFC40LOC.DLL) 的用途。

技术说明 57 (TN057) 阐述了可用于对组件进行本地化的某些设计和过程,可以是应用程序或 OLE 控件,也可以是使用 MFC 的 DLL。

技术说明 23 (TN023) 阐述了随 MFC 库一起提供且必需的标准资源。

有关随 Visual C++ 2.2 版或早期版本附带的 Microsoft 基础类的详细信息,请参阅 Microsoft 知识库中的以下文章:
147149 (http://support.microsoft.com/kb/147149/) “如何用基础类本地化应用程序资源”

Another article about this topic: http://dev.yesky.com/213/2199213.shtml



Q: How to build a resource-only DLL?

A: On the 'Project Menu', select 'Settings'. Select the 'Link' tab of the 'Project Settings' dialog, then in the 'Project Options' box, add the '/NOENTRY' option. '/NOENTRY' prevents the linker from linking a reference to '_main' into the DLL; this option is required to create a resource-only DLL.

Add the .RC file to an empty DLL project.

Build the DLL.

No MFC is involved in this process. If your application needs to access the resources from the DLL, it is easier to use the Win API functions to access these resources than MFC. You need to call 'LoadLibrary()' with the name of resource DLL, and then the Windows API 'FindResource()'/'LoadResource()'/'LoadBitmap()' etc. functions to find and load the resource.

The reason why the API functions are easier to manage than MFC is that the API functions require that you give it the handle to the loaded DLL (the return value when you called 'LoadLibrary()'), while the MFC functions do not have this parameter. Requiring the DLL handle allows much more flexibility, since you can have multiple resource DLL's loaded, and you don't have to fool around with the 'AfxSetResourceHandle()' function (for example, compare the MFC 'LoadBitmap()' with the Windows API 'LoadBitmap()'). When you call 'AfxSetResourceHandle()', you are globally making a change to which resources your application is going to reference, which I do not like, so I don't ever use that function.

If you want to use the MFC functions after using the API function to load your bitmap, just call the 'Attach()' method, and then the 'Detach()' method.
posted @ 2007-08-08 10:05  RayG  阅读(1184)  评论(0编辑  收藏  举报