Click here to Skip to main content
13,052,558 members (57,869 online)
Click here to Skip to main content
Add your own
alternative version


28 bookmarked
Posted 16 May 2007

MFC resources fallback

, 11 Jul 2007
Rate this:
Please Sign up or sign in to vote.
A little tip for implementing a fallback resources process with MFC that's useful for localization


This article explains a small but useful tip to implement a resource fallback process with MFC. With this tip, you can load resources dynamically from a DLL and if a resource isn't present in the DLL, it is loaded from main exe module.


My ideal localization pattern is to have the main EXE with embedded resources in the native language and, optionally, a resource-only DLL containing those resources to be localized. If a resource isn't present in the DLL, it has to be loaded from the EXE module. An important requisite is that resource has to be loaded by the default MFC functions.

If you try to implement this behaviour in MFC, you find a problem: while is very simple to override the default application resource handler with the DLL one, if a resource is missing in the DLL, it fails when loading. MFC provides a mechanism to load resources from an attached DLL if they are missing from the EXE using a global linked list (DLL chain). My idea is to attach the EXE to this DLL chain, so the resource loading process will search in the EXE if the resource isn't present in the DLL.

Using the code

To implement this tip, you need to add two private variables, m_hResDlland m_pExeModule, to your application class and override ExitInstance:

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

Now at the beginning of InitInstance, add this code:

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(), 
        //2 - puts DLL as principal resources supplier
        //now a resource is searched starting from resdll 
        //and if not found, is searched in
        //exe module

Then add some clean-up code in ExitInstance:

int CResFallbackApp::ExitInstance() 
    if(m_hResDll != NULL)
        delete m_pExeModule;
    return CWinApp::ExitInstance();

The trick consists of creating an object of type CDynLinkLibrary with the EXE module instance and resources handlers. The constructor of CDynLinkLibrary attaches itself to the DLL chain in the module state (trace into for more details). Now if you or MFC tries to load any kind of resource, it is searched first in the DLL if it is not found in the EXE. For example:

void CResFallbackDlg::OnTest() 
    CString sMsg;


If you want more details, trace into LoadString and you will arrive at the piece of code below from mfc\src\dllinit.cpp. Here you can see how resource seeking works.

int AFXAPI AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
    ASSERT(AfxIsValidAddress(lpszBuf, nMaxBuf*sizeof(TCHAR)));
    LPCTSTR lpszName = MAKEINTRESOURCE((nID>>4)+1);
    HINSTANCE hInst;
    int nLen;
    // first check the main module state
    AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
    if (!pModuleState->m_bSystem)
        hInst = AfxGetResourceHandle();
        if (::FindResource(hInst, lpszName, RT_STRING) != NULL &&
            (nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
            // found a non-zero string in app
            return nLen;
     // check non-system DLLs in proper order
     for (CDynLinkLibrary* pDLL = 
         pModuleState->m_libraryList; pDLL != NULL;
     pDLL = pDLL->m_pNextDLL)
         if (!pDLL->m_bSystem && (hInst = pDLL->m_hResource) != NULL &&
             ::FindResource(hInst, lpszName, RT_STRING) != NULL &&
             (nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
             return nLen;

Points of interest

This tip is useful for localization in this scenario:

  1. Build your EXE with embedded native resource.
  2. Extract resources with some specific localization tool.
  3. With the localization tool, translate resources and create a res-only DLL
  4. Provide to your customer the EXE with his language DLL.
  5. When in the future you patch only the EXE without modifying resources, redistribute the EXE only.
  6. When in the future you add new resources to your EXE, if you add new resources with new IDs you can deploy the EXE and the customer will see old things translated and new things in the default language while waiting for the translation process. When the new translation completes, you have to deploy only the DLL.


  • 16 May, 2007 -- Original version posted
  • 11 July, 2007 -- Article edited and moved to the main article base


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Giuseppe Marazzi
Web Developer
Italy Italy
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionGerman resources loaded from resource only dll when system locale is french Pin
anandmampuzhakal12-Nov-15 0:01
memberanandmampuzhakal12-Nov-15 0:01 
GeneralMy vote of 5 Pin
JunfengGuo22-Apr-14 16:47
memberJunfengGuo22-Apr-14 16:47 
GeneralThanks Pin
Matt Clarkson23-Oct-09 0:45
memberMatt Clarkson23-Oct-09 0:45 
GeneralMFC static linking Pin
sashoalm13-May-09 22:10
membersashoalm13-May-09 22:10 
GeneralGood work! Pin
Hans Dietrich11-Jul-07 11:03
mvpHans Dietrich11-Jul-07 11:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170713.1 | Last Updated 11 Jul 2007
Article Copyright 2007 by Giuseppe Marazzi
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid