Solved

destroying a menu when application ends without resource-leaks

Posted on 1997-06-11
2
255 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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Expand LInux Boot partition remotly 3 90
sum67 challenge 35 98
matchUp  challenge 9 108
How to convert MFC::CString to UTF8 wchar_t* 10 210
In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

777 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