Click here to Skip to main content
15,885,767 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The code segment of my frame window class(Main window class) that is relevant to this question is this:

C++
protected:  // control bar embedded members
	CMFCMenuBar       m_wndMenuBar;
	CMyToolBar        m_wndToolBar;
	CMFCStatusBar     m_wndStatusBar;
	CMFCToolBarImages m_UserImages;


The problem is that esach time attempt to use the CMenu pointer returned by GetMenu() function within of my message handlers an exception is thrown. This illustrated below:

C++
void CMainFrame::Handler()
{
   CMenu *pMainMenu = GetMenu();

   CMenu * pSubMenu = pMainMenu->GetSubmenu(0);

   pSubMenu->InsertMenu(0,MF_BYPOSITION | MF_STRING,IDM_RESET,_T("&Reset"));//This line won't execute
}


The exception thrown reports that the m_hMenu member of pSubMenu is not valid. What could be wrong?


EDIT:

For some inexplicable reasons, I can get GetMenu() function to work. In the program above an attempt is made to get a pointer to the FILE submenu of a windows app, but without success.

Please what can be wrong? Or better still, can someone show me a simple mfc code to get the pointer to the FILE menu( which I beleive is a submenu) submenu of a windows app?

EDIT1:
On throwing an exeption the file

afxwin1.inl
C++
FXWIN_INLINE CMenu* CMenu::GetSubMenu(int nPos) const
	{ ASSERT(::IsMenu(m_hMenu)); return CMenu::FromHandle(::GetSubMenu(m_hMenu, nPos)); }/*A pointer points to this line as the location of the exception.*/


A dialogue box displayed the message:
Unhandled exeption at 0x50b9a12c (mfc1ooud.dll) in App.exe:
)xC0000005: Access violation reading 0x00000004


What could really be wrong? Or could it be because my app used three different document template and as such have three different menu resource eac for each template and file type.

EDIT2:

I put the following code line immediately after GetMenu in the code segment above.
C++
ASSERT(m_pMainMenu);


That inclusion revealed that GetMenu() did not return a valid result.
What could make GetMenu() fail. The enclosing function is a member of a class difined as shown below.
C++
class CMainFrame : public CMDIFrameWndEx
{
}

Is it that GetMenu() function can not return a pointer to the menu attached to a CMDIFrameWndEx object? If yes, how does one get a pointer to the menu attached to the CMDIFrameWndEx object?


NEW EDIT3
This is the code I am usng now. The message box reports insert success, but I couldn't see the newly inserted menu. What could be wrong?

C++
const CMFCMenuBar *pMenuBar = GetMenuBar();

	HMENU hMainMenu = NULL;
	HMENU hSubMenu = NULL;

	hMainMenu = pMenuBar->GetHMenu();
	ASSERT(hMainMenu);
	hSubMenu = GetSubMenu(hMainMenu,0);
	ASSERT(hSubMenu);
	
	if(InsertMenu(hSubMenu,0,MF_BYPOSITION | MF_STRING,ID_TEST_FIRST,_T("&This is a test")))
	{
		MessageBox(_T("Insert Success"));
	}
	DrawMenuBar();
Posted
Updated 23-Jul-15 22:26pm
v7

There is probably no sub menu (pSubMenu is NULL). GetSubMenu() is used to get a pop-up (context) menu. But it looks like you want to access the main menu of your application.

[EDIT]
The above may be unclear. GetSubmenu() will only return a valid pointer when the passed position refers to a sub menu. It will return NULL otherwise (e.g. menu item or a separator).

Use GetMenuItemInfo[^] to check for the item type.

[EDIT 2]
The updated question indicates that you are using a CMDIFrameWndEx inherited class. That handles menus in a different way and provides the GetMenuBar[^] function return a pointer to CMFCMenuBar. Use that pointer with GetHMenu to get the menu handle.
 
Share this answer
 
v3
Comments
Gbenbam 22-Jun-15 7:00am    
ok. how do i get a pointer to a menu item on my main menu for ,instance, the FILE menu?
Jochen Arndt 22-Jun-15 7:21am    
My answer is may be unclear. I will update it.
Gbenbam 22-Jul-15 22:53pm    
I have not been able to resolve the "GetMenu() not working" problem. Please refer to the edited version of my question.
Gbenbam 23-Jul-15 7:08am    
Dubbuging has shown that is is GetMenu() that failed please see the new revalation as see if you can help provide a solution to the modified question. Thank you.
Jochen Arndt 23-Jul-15 7:50am    
See my updated solution.
As per the documentation[^]:

A pointer to a CMenu object whose m_hMenu member contains a handle to the pop-up menu if a pop-up menu exists at the given position; otherwise NULL.


there is no pop-up menu at 0 position in your case.
 
Share this answer
 
Comments
Gbenbam 23-Jul-15 6:08am    
Please, what position is the FILE menu of a windows application? And, please is it a popup menu?

Can you kindly show me how to get a pointer to the FILE menu of a windows application which usually the first menu in a windows application.
CPallini 23-Jul-15 6:13am    
Have a look at MSDN sample code:
https://msdn.microsoft.com/en-us/library/5cb7500e.aspx
Gbenbam 23-Jul-15 6:27am    
The example code shown there is more or less identical to my code above. The menu location zero was used to get a pointer to the FILE menu.This is exactly why I find the fact that my code is not working mysterious.Or can you see any special differnce between my code and that on MSDN apart from use of AfxGetMainWnd() ?

Gbenbam 23-Jul-15 7:09am    
Dubbuging has shown that is is GetMenu() that failed please see the new revalation as see if you can help provide a solution to the modified question. Thank you.
CPallini 23-Jul-15 7:38am    
As far as I can see you should check pMainMenu instead of m_MainMenu.
See https://msdn.microsoft.com/en-us/library/7xkd69hf.aspx[^]. Try this code, and step through with your debugger to ensure it works correctly.
 
Share this answer
 
Comments
Gbenbam 31-Jul-15 22:33pm    
Perhaps you should have a look at my solution below.
I was able solve the mystery myself. I found many of the common menu function wont work. MS has made every item on the toolbar objects. The number of objects associated with a popup menu alone is shocking.

I found out that generally when a menu altering operation has been carried out, rather that calling DrawMenuBar as was the case, the right thing to do is to call:

m_wndMenuBar.AdjustLayout();
m_wndMenuBar.AdjustSizeImmediate();

in order to effect the change.

The following are sample codes that I was able to use to get the desired menu changes.I was able to figure out what to do after spending considerable time on MSDN.

C++
void CMainFrame::ChangeMenu()
{
	CMenu menu,menu1;
	
	menu.CreatePopupMenu();
	CreateFileMenu(menu.m_hMenu);
	m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,szMenuName),0);
	m_wndMenuBar.AdjustLayout();
    m_wndMenuBar.AdjustSizeImmediate();

	m_wndMenuBar.RemoveButton(1);
	m_wndMenuBar.AdjustLayout();
    m_wndMenuBar.AdjustSizeImmediate();

	menu1.CreatePopupMenu();
	CreateAccessMenu(menu1.m_hMenu);
	m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu1, -1,m_szUserName),3);
	m_wndMenuBar.AdjustLayout();
    m_wndMenuBar.AdjustSizeImmediate();

}



C++
void CMainFrame::SetUserName()
{
	int iCount = m_wndMenuBar.GetCount();
	for(int i = 0; i < iCount; i++)
	{
		CString stText;
		m_wndMenuBar.GetButtonText(i,stText);
		if(!lstrcmp(stText,szMenuAccess))
		{
			m_wndMenuBar.SetButtonText(i,m_szUserName);
			m_wndMenuBar.AdjustLayout();
			m_wndMenuBar.AdjustSizeImmediate();
			return;
		}
	}
}


The following are the definition, if you will, of the functions called in the two menu altering programs above.

C++
bool CreateFileMenu(HMENU hPopup)
	{
		//Create NEW sub menu
		HMENU hNewPopup = CreatePopupMenu();
		InsertMenu(hNewPopup,0,MF_BYPOSITION|MF_STRING,IDM_FILE_NEW_TEMPLATE1,_T("Template1"));
		InsertMenu(hNewPopup,1,MF_BYPOSITION|MF_STRING,IDM_FILE_NEW_TEMPLATE2,_T("Template2"));
		InsertMenu(hNewPopup,2,MF_BYPOSITION|MF_STRING,IDM_FILE_NEW_TEMPLATE3,_T("Template3"));
		InsertMenu(hNewPopup,3,MF_BYPOSITION|MF_STRING,IDM_FILE_NEW_TEMPLATE4,_T("Template4"));

		InsertMenu(hPopup,0,MF_BYPOSITION|MF_POPUP,(UINT_PTR)hNewPopup,_T("&New"));
		InsertMenu(hPopup,1,MF_BYPOSITION | MF_STRING,ID_FILE_OPEN,_T("&Open \tCtrl+O"));
		InsertMenu(hPopup,2,MF_BYPOSITION | MF_STRING,ID_APP_EXIT,_T("E&xit"));

		return true;
	}



C++
bool CreateAccessMenu(HMENU hPopup)
   {
       //Create NEW sub menu
       HMENU hNewPopup = CreatePopupMenu();

       InsertMenu(hPopup,0,MF_BYPOSITION | MF_STRING,ID_ACCESS_EXITACCESS,_T("Exit Access"));

       return true;
   }



Thanks all.I hope someone finds this helpful
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900