Search code examples
c++localizationmfcribbonassert

MFC ribbon interface gives assert failure when localizing app


I have an MFC-based app that uses the Office 2007 ribbon interface. MFC is statically linked.

I'm trying to add Japanese localization. I have the localized resources in a separate DLL. I'm loading the resource DLL at the beginning of InitInstance:

VERIFY(hRes = LoadLibrary(_T("JapaneseLang.dll")));
if(hRes)
    AfxSetResourceHandle(hRes);

This causes an assert failure at CMFCVisualManagerOffice2007::OnUpdateSystemColors

#if !defined _AFXDLL
        TRACE(_T("\r\nImportant: to enable the Office 2007 look in static link,\r\n"));
        TRACE(_T("include afxribbon.rc from the RC file in your project.\r\n\r\n"));
        ASSERT(FALSE);
#endif

But I do have afxribbon.rc included in the rc files of both the DLL and the EXE.


I also found a similar question asked at tech-archive.net and a possible solution is outlined there

Now i find the error location. this shoule be a bug of new mfc version.

In the CMFCVisualManagerOffice2007 ,when the style is changing , the function SetStyle of CMFCVisualManagerOffice2007 auto call FreeLibrary to free the dll, so the error happend.

Now i derived a class from CMFCVisualManagerOffice2007 and add a static function to set the member variable m_bAutoFreeRes , by doing this the application can run correctly; see bellow.

class CMFCVisualExtManagerOffice2007 : public CMFCVisualManagerOffice2007 { DECLARE_DYNCREATE(CMFCVisualExtManagerOffice2007) public: CMFCVisualExtManagerOffice2007(); virtual ~CMFCVisualExtManagerOffice2007();

static void SetAutoFreeRes(BOOL bAutoFree = FALSE) { m_bAutoFreeRes = bAutoFree; } };


But I have trouble understanding what exactly causes the problem, and how this solution works. Also I'm not sure if it is a correct solution. Does anyone know what exactly causes this problem, and how the solution works?


Solution

  • I figured out how the solution works. I need to set m_bAutoFreeRes to false after each call to CMFCVisualManagerOffice2007::SetStyle.

    class CMFCVisualExtManagerOffice2007 : public CMFCVisualManagerOffice2007
    {
        DECLARE_DYNCREATE(CMFCVisualExtManagerOffice2007)
    public:
        CMFCVisualExtManagerOffice2007();
        virtual ~CMFCVisualExtManagerOffice2007();
    
        static void SetAutoFreeRes(BOOL bAutoFree = FALSE)
        {
            m_bAutoFreeRes = bAutoFree;
        }
    };
    

    and then when switching between the themes

        switch (m_nAppLook)
        {
        case ID_VIEW_APPLOOK_OFF_2007_BLUE:
            CMFCVisualManagerOffice2007::SetStyle (CMFCVisualManagerOffice2007::Office2007_LunaBlue);
            CMFCVisualExtManagerOffice2007::SetAutoFreeRes(FALSE);
            break;
    
        case ID_VIEW_APPLOOK_OFF_2007_BLACK:
            CMFCVisualManagerOffice2007::SetStyle (CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
            CMFCVisualExtManagerOffice2007::SetAutoFreeRes(FALSE);
            break;
    
        case ID_VIEW_APPLOOK_OFF_2007_SILVER:
            CMFCVisualManagerOffice2007::SetStyle (CMFCVisualManagerOffice2007::Office2007_Silver);
            CMFCVisualExtManagerOffice2007::SetAutoFreeRes(FALSE);
            break;
    
        case ID_VIEW_APPLOOK_OFF_2007_AQUA:
            CMFCVisualManagerOffice2007::SetStyle (CMFCVisualManagerOffice2007::Office2007_Aqua);
            CMFCVisualExtManagerOffice2007::SetAutoFreeRes(FALSE);
            break;
        }