-
"Recent Files"

If you have "Recent Files" you must use LoadStdProfileSettingsEx instead of LoadStdProfileSettings, on the derived class from CWinApp.
A new class is used in LoadStdProfileSettingsEx: CRecentFileListEx derived from CRecentFileList.
BOOL CSampleMenuApp::InitInstance()
{
LoadStdProfileSettingsEx(_AFX_MRU_COUNT);
return TRUE;
};
If you don't have "Recent Files" or _AFX_MRU_COUNT = 0, you can eliminate CRecentFileListEx class and void LoadStdProfileSettingsEx(UINT nMaxMRU); function.
All this are used for handling items which are added at run time on "Recent Files" section menu.
-
"Active Windows"

If you use "Active Windows" it is a little bit hard to handle items which are inserted at run time with message WM_MDISETMENU.
On each child frame, you must implement virtual void OnUpdateFrameMenu(BOOL bActive, CWnd* pActivateWnd, HMENU hMenuAlt); as follows:
void CChildFrame::OnUpdateFrameMenu(BOOL bActivate,
CWnd* pActivateWnd, HMENU hMenuAlt)
{
CMDIChildWnd::OnUpdateFrameMenu(bActivate, pActivateWnd, hMenuAlt);
((CMainFrame*)GetParentFrame())->RefreshInternalMenu();
}
This is a virtual function from CMDIChildWnd which updates the frame menu, and you must inform the ColorMenu that "Active Windows" menu was changed with RefreshInternalMenu function.
On CMainFrame, you must define RefreshInternalMenu() as following:
void CMainFrame::RefreshInternalMenu()
{
m_IdTimer = SetTimer(INTERNAL_UPDATE_TIMER, 50, NULL);
}
and on timer function you must do this:
void CMainFrame::OnTimer(UINT nIDEvent)
{
if(nIDEvent == INTERNAL_UPDATE_TIMER)
{
KillTimer(m_IdTimer);
m_IdTimer = NULL;
HMENU hMenuWindow = GetWindowMenuPopup(GetMenuOfView());
CColorMenu* pMenu = m_menuChildFrame.FindSubMenu(hMenuWindow);
if(pMenu)
pMenu->RefreshMenusForMDIs();
}
CMDIFrameWnd::OnTimer(nIDEvent);
}
All this must be done with a timer because UpdateFrameMenu is made as "delayed refresh". If you will not use the timer, you will "not see the new updated menu", you will see menu unchanged.
-
"Final step"
On CMainFrame, you must define all menus: one for CMainFrame and the rest for child frames (if you have more than one).
class CMainFrame : public CMDIFrameWnd
{
HMENU GetMenuOfView(){return m_menuChildFrame.GetSafeHmenu();}
CColorMenu m_menuMainFrame;
CColorMenu m_menuChildFrame;
}
So, if you have more child frames with different menus, you must define more CColorMenu m_menuChildFrame;
On CMainFrame::OnCreate you must just load menus, set the needed icons and replace the default menu as follows:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_menuMainFrame.LoadMenu(IDR_MAINFRAME);
m_menuChildFrame.LoadMenu(IDR_SAMPLETYPE);
m_menuMainFrame.SetIconToHandle(ID_FILE_NEW, IDI_ICON_NEW);
HMENU OldMenuDefault = m_hMenuDefault;
SetMenu(&m_menuMainFrame);
m_hMenuDefault = m_menuMainFrame.GetSafeHmenu();
::DestroyMenu(OldMenuDefault);
}
After that you must implement CMainFrame::OnMeasureItem as follows:
void CMainFrame::OnMeasureItem(int nIDCtl,
LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if(lpMeasureItemStruct->CtlType == ODT_MENU)
{
if(m_menuMainFrame.IsMenu((HMENU)lpMeasureItemStruct->itemID))
{
m_menuMainFrame.MeasureItem(lpMeasureItemStruct);
return;
}
if(m_menuChildFrame.IsMenu((HMENU)lpMeasureItemStruct->itemID))
{
m_menuChildFrame.MeasureItem(lpMeasureItemStruct);
return;
}
}
CMDIFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
};
And destroy the menus... on CMainFrame::OnDestroy().
void CMainFrame::OnDestroy()
{
SetMenu(NULL);
::DestroyMenu(m_hMenuDefault);
m_hMenuDefault = NULL;
m_menuMainFrame.DestroyMenu();
m_menuChildFrame.DestroyMenu();
CMDIFrameWnd::OnDestroy();
}
And last, on each child frame, on CChildFrame::OnCreate, replace the default menu.
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CMainFrame* pFram = (CMainFrame*)GetParentFrame();
HMENU OldMenuDefault = m_hMenuDefault;
m_hMenuDefault = pFram->GetMenuOfView();
m_hMenuShared = m_hMenuDefault;
::DestroyMenu(OldMenuDefault);
}
And on destroy, prevent not to destroy the default menu.
void CChildFrame::OnDestroy()
{
m_hMenuShared = NULL;
m_hMenuDefault = NULL;
CMDIChildWnd::OnDestroy();
}
Have luck!