Solved

destroying a menu when application ends without resource-leaks

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
how to monitor remote shell execution on linux 9 97
countEvens challenge 2 77
NotAlone Challenge 20 80
Annoying "thing" blocks my view 4 82
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…
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 …
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.
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.

895 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

12 Experts available now in Live!

Get 1:1 Help Now