![]() |
Desktop Development »
Menus »
Custom menus
Intermediate
Owner Drawn Menu with Icons, Fade 2D-3D Horizontal/VerticalBy Dascalescu RomyThis article describes an owner drawn menu with icons, fade 2D-3D horizontal/vertical. |
VC6, Windows, MFC, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
The used colors are just for highlighting the power of the menu, they can be changed.
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
COLORREF m_Bk2DPop; // Start color (background) at 2D on pop-up menus COLORREF m_Txt2DPop; // Text color at 2D on pop-up menus COLORREF m_Bk2DMen; // Start color (background) at 2D on menus COLORREF m_Txt2DMen; // Text color at 2D on menus COLORREF m_Bk3DPop; // Start color (background) at 3D on pop-up menus COLORREF m_Txt3DPop; // Text color at 3D on pop-up menus COLORREF m_Bk3DMen; // Start color (background) at 3D on menus COLORREF m_Txt3DMen; // Text color at 2D on menus COLORREF m_Fade2DPop; // End color for 2D used at FADE on pop-up menus COLORREF m_Fade3DPop; // End color for 3D used at FADE on pop-up menus COLORREF m_Fade2DMen; // End color for 2D used at FADE on menus COLORREF m_Fade3DMen; // End color for 3D used at FADE on menus protected: // settings of control COLORREF m_ColCheck; // Color of Check COLORREF m_ColSepar; // Color of separator(MF_SEPARATOR) COLORREF m_BkGray; // Color background for Gray value COLORREF m_TxtGray; // Color text for Gray value UINT m_FadeTypeMen; // At 2D FADE for menu start //color m_Bk2DMen TO end //color m_Fade2DMen for menus // At 3D FADE for menu start color //m_Bk3DMen TO end color m_Fade3DMen for menus UINT m_FadeTypePop; // At 2D FADE for menu start //color m_Bk2DPop TO end //color m_Fade2DPop for pop-up menus // At 3D FADE for menu start color //m_Bk3DPop TO end color //m_Fade3DPop for pop-up menus int m_Val3D; // Deep 3D value int m_HeightSep; // Height of separator int m_HeightCel; // Height of a menu item int m_WidthCel; // Width of a menu item VTYPE_ITEMCONT* m_itemsStr; // internal Use VTYPE_MENUCOLOR* m_HandlesMenu; // internal Use

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()
{
//...................
// Load standard INI file options (including MRU)
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.
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.
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; // Load menus m_menuMainFrame.LoadMenu(IDR_MAINFRAME); m_menuChildFrame.LoadMenu(IDR_SAMPLETYPE); // set the icon to items if you want m_menuMainFrame.SetIconToHandle(ID_FILE_NEW, IDI_ICON_NEW); //.................... // replace the default menu HMENU OldMenuDefault = m_hMenuDefault; SetMenu(&m_menuMainFrame); m_hMenuDefault = m_menuMainFrame.GetSafeHmenu(); ::DestroyMenu(OldMenuDefault); // if you set skin please make so: /* CSSkin skin; // ........... m_menuMainFrame.SetSkin(&skin); DrawMenuBar(); */ }
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); // if you set skin please make so: /* CSSkin skin; // ........... pFram->m_menuChildFrame.SetSkin(&skin); DrawMenuBar(); */ }
And on destroy, prevent not to destroy the default menu.
void CChildFrame::OnDestroy()
{
m_hMenuShared = NULL;
m_hMenuDefault = NULL;
CMDIChildWnd::OnDestroy();
}
Have luck!
| You must Sign In to use this message board. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 29 Nov 2003 Editor: Smitha Vijayan |
Copyright 2003 by Dascalescu Romy Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |