The used colors are just for highlighting the power of the menu, they can be changed.
Introduction
Principal class is CColorMenu
:
#define FADE_NONE 0x00 // No 3D Fade
#define FADE_HORZ 0x01 // Fade 3D HORZ
#define FADE_VERT 0x02 // Fade 3D VERT
#define FADE2D_NONE 0x00 // No 2D Fade
#define FADE2D_HORZ 0x10 // Fade 2D HORZ
#define FADE2D_VERT 0x20 // Fade 2D VERT
#define MENU_NONE 0x00 // undefined type of menu
#define MENU_SIMPLE 0x01 // normal menu item
#define MENU_POPUP 0x02 // pop-up menu item
Members
COLORREF m_Bk2DPop;
COLORREF m_Txt2DPop;
COLORREF m_Bk2DMen;
COLORREF m_Txt2DMen;
COLORREF m_Bk3DPop;
COLORREF m_Txt3DPop;
COLORREF m_Bk3DMen;
COLORREF m_Txt3DMen;
COLORREF m_Fade2DPop;
COLORREF m_Fade3DPop;
COLORREF m_Fade2DMen;
COLORREF m_Fade3DMen;
protected:
COLORREF m_ColCheck;
COLORREF m_ColSepar;
COLORREF m_BkGray;
COLORREF m_TxtGray;
UINT m_FadeTypeMen;
UINT m_FadeTypePop;
int m_Val3D;
int m_HeightSep;
int m_HeightCel;
int m_WidthCel;
VTYPE_ITEMCONT* m_itemsStr;
VTYPE_MENUCOLOR* m_HandlesMenu;
Steps
-
"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!
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.