MFC资源回退机制实现

在多语言软件开发中,资源的本地化是一个重要的环节。本文将介绍一种在MFC应用程序中实现资源回退机制的方法,该方法允许动态地从DLL加载资源,如果DLL中不存在该资源,则从主EXE模块中加载。

理想的本地化模式是将主EXE模块嵌入本地语言资源,并可选地使用资源专用DLL来包含那些需要本地化的资源。如果DLL中缺少资源,则必须从EXE模块中加载。一个重要的要求是资源必须由默认的MFC函数加载。

实现过程

MFC中实现这种行为时,会遇到一个问题:虽然很容易用DLL覆盖默认应用程序资源处理程序,但如果DLL中缺少资源,则加载时会失败。MFC提供了一种机制,如果EXE中缺少资源,则从附加的DLL加载资源,使用全局链接列表(DLL链)。想法是将EXE附加到这个DLL链上,这样资源加载过程将首先在DLL中搜索资源,如果不在DLL中,则在EXE模块中搜索。

要实现这个提示,需要在应用程序类中添加两个私有变量,m_hResDll和m_pExeModule,并覆盖ExitInstance:

class CResFallbackApp : public CWinApp { public: CResFallbackApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CResFallbackApp) public: virtual BOOL InitInstance(); virtual int ExitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CResFallbackApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() private: HMODULE m_hResDll; CDynLinkLibrary* m_pExeModule; };

然后在InitInstance的开始处添加以下代码:

BOOL CResFallbackApp::InitInstance() { // Search resources dll m_hResDll = LoadLibrary(_T("ResDll.dll")); // put here better way to find the right dll if (m_hResDll != NULL) { // if found: // 1 - puts EXE module in extension DLL chain // (using an instance of CDynLinkLibrary) m_pExeModule = new CDynLinkLibrary(AfxGetInstanceHandle(), AfxGetResourceHandle()); // 2 - puts DLL as principal resources supplier AfxSetResourceHandle(m_hResDll); // now a resource is searched starting from resdll // and if not found, is searched in exe module } }

然后在ExitInstance中添加一些清理代码:

int CResFallbackApp::ExitInstance() { // cleaning if (m_hResDll != NULL) { delete m_pExeModule; FreeLibrary(m_hResDll); } return CWinApp::ExitInstance(); }

关键在于创建一个CDynLinkLibrary类型的对象,使用EXE模块实例和资源处理程序。CDynLinkLibrary的构造函数将自己附加到模块状态中的DLL链上(深入跟踪以获取更多细节)。现在,如果或MFC尝试加载任何类型的资源,它首先在DLL中搜索,如果没有找到,则在EXE中搜索。例如:

void CResFallbackDlg::OnTest() { CString sMsg; sMsg.LoadString(IDS_TEST); AfxMessageBox(sMsg); sMsg.LoadString(IDS_TEST2); AfxMessageBox(sMsg); }

如果想要更多细节,可以跟踪LoadString,将到达mfc\src\dllinit.cpp中的以下代码片段。在这里,可以看到资源搜索是如何工作的。

应用场景

这个提示在以下本地化场景中非常有用:

  • 构建带有嵌入式本地资源的EXE。
  • 使用特定的本地化工具提取资源。
  • 使用本地化工具翻译资源并创建资源专用DLL
  • 向客户提供带有他语言的EXE DLL。
  • 将来,如果只修补EXE而不修改资源,只需重新分发EXE。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485