Solved

destroying a menu when application ends without resource-leaks

Posted on 1997-06-11
2
253 Views
Last Modified: 2013-11-20
Hello,

In brief: how can a menu which was loaded from a separate resource-dll be destroyed at application-end, without leaving any resource-leaks?

I have seperate resource-DLL's for each language I want to support.
In InitInstance I post a user-defined message WM_CHANGELANGUAGE to activate the desired resource-DLL, and to activate the according menu.
This user-defined message WM_CHANGELANGUAGE is called every time the user wants to change the language of the application.
The according message-handler is OnChangeLanguage.
To avoid resource-leaks it is necessary to destroy the previously loaded menu before setting the new one.
But -for some reason- the initial (the default) menu mustn't ever be deleted, so a CMenu* to the default menu is needed to assure that the default menu isn't deleted! I get a pointer to this default-menu via the user-defined WM_GETDEFAULTMENU-message in InitInstance and OnGetDefaultMenu respectively.

The problem I have is: When closing the application the last loaded menu must be destroyed. (In CMainFrame::OnDestroy) But only if it isn't the default-menu!
But on the other hand MFC will bring an error, when it destroys the Mainframe with no menu attached at all. So I thought it would be necessary to set the default menu again to make the MFC happy, but this doesn't work either!

So: how the heck can multiple menus be handled correctly, without leaving any resource leaks?

Thanks a bunch :-)

The source code is:
void CMainFrame::OnDestroy()
{
      CMenu* pMenu = GetMenu();
      if( pMenu != m_pMenuDefault)
      {
            // Destroy the no longer used menu unless it's the default
            // menu as MFC insists on restoring that at close
            pMenu->DestroyMenu();
      }

      HINSTANCE hInstRes = AfxGetResourceHandle();
      HINSTANCE hInst = AfxGetInstanceHandle();
      if (hInstRes != hInst)
      {
            FreeLibrary (hInstRes);
            AfxSetResourceHandle (hInst);
      }

      SetMenu(m_pMenuDefault);


      CMDIFrameWnd::OnDestroy();
}

BOOL CMyApp::InitInstance()
{
      ....
      ....
      pMainFrame->PostMessage(WM_GETDEFAULTMENU);
      pMainFrame->PostMessage(WM_CHANGELANGUAGE,LANG_ENGLISH);

      // The main window has been initialized, so show and update it.
      pMainFrame->ShowWindow(m_nCmdShow);
      pMainFrame->UpdateWindow();

      return TRUE;
}

LRESULT CMainFrame::OnChangeLanguage(WPARAM wParam, LPARAM lParam)
{
CString strLangDLL;

      if (wParam == LANG_ENGLISH)      // load english resource-dll
            strLangDLL = "e:\\prj\\lang\\res_eng.dll";
      else if (wParam == LANG_GERMAN)      // load german resource-dll
            strLangDLL = "e:\\prj\\lang\\res_dts.dll";
      else
            return 0L;

      HINSTANCE hInstRes = AfxGetResourceHandle();
      HINSTANCE hInst = AfxGetInstanceHandle();
      if (hInstRes != hInst)
      {
            FreeLibrary (hInstRes);
            AfxSetResourceHandle (hInst);
      }
      if ((int)(hInstRes = AfxLoadLibrary(strLangDLL)) < HINSTANCE_ERROR)
            return 0L;
      AfxSetResourceHandle(hInstRes);

      CMenu menu;
      if( menu.LoadMenu(IDR_LANGTYPE))
      {      
            CMenu* pMenu = GetMenu();
            if( pMenu != m_pMenuDefault)
            {
                  // Destroy the no longer used menu unless it's the default
                  // menu as MFC insists on restoring that at close
                  pMenu->DestroyMenu();
            }
            SetMenu(&menu);
            menu.Detach();
      }
      m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));
      m_wndStatusBar.UpdateWindow();

      return 0L;
}

LRESULT CMainFrame::OnGetDefaultMenu(WPARAM wParam, LPARAM lParam)
{
      m_pMenuDefault = AfxGetMainWnd()->GetMenu();
      return 0L;
}

0
Comment
Question by:Sherpa
  • 2
2 Comments
 
LVL 4

Expert Comment

by:AVaulin
ID: 1302062
May be it's stupid answer... But how about this idea: use ModifyMenu CMenu method (or API function) to modify menu items text. If you use StatusBar and ToolBar and you want to change description text language you can copy all string resource and modify them (say if you have IDM_FILE add IDM_FILE1 item and use it as nIDNewItem). Also you need to handle both IDM_FILE and IDM_FILE1 commands (use say OnFile method for both). I've used this idea in my program. All work fine.
Try and good luck.
0
 
LVL 4

Accepted Solution

by:
AVaulin earned 120 total points
ID: 1302063
OK! I propose you also one way. Add flobal integer variable which contain menu loading number and init it with zero. When you are load menu increase it, when destroy - at first check that this variable more then zero and if yes - destroy menu and decrease variable. I hope this will help. Good luck.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now