Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

destroying a menu when application ends without resource-leaks

Posted on 1997-06-11
2
Medium Priority
?
275 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
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 a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…

604 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