Click here to Skip to main content
15,867,488 members
Articles / Mobile Apps / Windows Mobile

Cool Owner Drawn Menus with Bitmaps - Version 3.03

Rate me:
Please Sign up or sign in to vote.
4.92/5 (76 votes)
28 Apr 2002CPOL15 min read 1.2M   16.9K   268  
This class implements an owner drawn menu class that mimics the menu style used in XP, Office and Visual C++
// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "mymenu.h"
#include "MainFrm.h"
#include "MymenuDoc.h"
#include "MyFrame.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int Undocheck=0;
/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_COMMAND(ID_ZOOM, OnZoom)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_WM_MEASUREITEM()
	ON_WM_MENUCHAR()
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_UPDATE_COMMAND_UI(ID_ZOOM, OnUpdateZoom)
	ON_COMMAND(ID_DEFAULT, OnDefault)
	ON_UPDATE_COMMAND_UI(ID_DEFAULT, OnUpdateDefault)
	ON_WM_INITMENUPOPUP()
	ON_COMMAND(ID_HOMEPAGE, OnHomepage)
	ON_COMMAND(ID_ENABLE, OnEnable)
	ON_UPDATE_COMMAND_UI(ID_ENABLE, OnUpdateEnable)
	ON_COMMAND(ID_DISABLE, OnDisable)
	ON_UPDATE_COMMAND_UI(ID_DISABLE, OnUpdateDisable)
	ON_COMMAND(ID_ADD_MENU_OPTIONS, OnAddMenuOptions)
	ON_UPDATE_COMMAND_UI(ID_ADD_MENU_OPTIONS, OnUpdateAddMenuOptions)
	ON_COMMAND(ID_REMOVE_ZOOM, OnRemoveZoom)
	ON_COMMAND(ID_MENU2, OnMenu2)
	ON_UPDATE_COMMAND_UI(ID_MENU2, OnUpdateMenu2)
	ON_COMMAND(ID_ZOOMS, OnZooms)
	ON_COMMAND(ID_NEW, OnNew)
	ON_COMMAND(ID_TILE, OnTile)
	ON_COMMAND(ID_JUNK, OnJunk)
	ON_COMMAND(ID_NET, OnNet)
	ON_COMMAND(ID_NEW_DOC_TEMPLATE, OnNewDocTemplate)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
	// TODO: add member initialization code here
	zoomcheck=TRUE;
  zoomflag=TRUE;
  disable_flag=FALSE;
  menu2flag=FALSE;
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.Create(this) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}

	// TODO: Remove this if you don't want tool tips or a resizeable toolbar
	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
		CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

	// TODO: Delete these three lines if you don't want the toolbar to
	//  be dockable
	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);

  CMenu *pSystemMenu=GetSystemMenu(FALSE);
  pSystemMenu->AppendMenu(MF_SEPARATOR);
  pSystemMenu->AppendMenu(MF_STRING,IDM_SYSMENU_ABOUT,_T("&About MyApp")); //SK modified for Unicode

	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CMDIFrameWnd::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CMDIFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CMDIFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers

void CMainFrame::OnZoom() 
{
	zoomcheck=!zoomcheck;
}

void CMainFrame::OnEditUndo() 
{
Undocheck=!Undocheck;	
}

HMENU CMainFrame::NewMenu()
{
  static UINT toolbars[]={
    IDR_MAINFRAME,
    IDR_TOOLBAR
  };

  // Load the menu from the resources
  m_menu.LoadMenu(IDR_MYMENUTYPE);

  // Use ModifyODMenu to add a bitmap to a menu options.The first parameter
  // is the menu option text string.If it's NULL, keep the current text
  // string.The second option is the ID of the menu option, or the menu
  // option text (use this for adding bitmaps to popup options) to change.
  // The third option is the resource ID of the bitmap.This can also be a
  // toolbar ID in which case the class searches the toolbar for the
  // appropriate bitmap.Only Bitmap and Toolbar resources are supported.
  m_menu.ModifyODMenu(NULL,ID_WINDOW_TILE_HORZ,IDB_WINDOW_TILE);
  m_menu.ModifyODMenu(NULL,_T("&Rocscience on the Web"),IDB_NET);

	// Instead of a resource you can use a CBitmap object with ModifyODMenu

	HBITMAP hbmp=BCMenu::LoadSysColorBitmap(IDB_NET);
  if(hbmp){
    CBitmap bmp;
    bmp.Attach(hbmp);
    m_menu.ModifyODMenu(NULL,ID_NET,&bmp);
    bmp.Detach();
    DeleteObject(hbmp);
  }

	// Instead of a resource you can use a CImageList object with ModifyODMenu
	CImageList temp;
  temp.Create(16,15,ILC_COLORDDB|ILC_MASK,1,1);
	m_menu.AddBitmapToImageList(&temp,IDB_ZOOM);
  m_menu.ModifyODMenu(NULL,ID_ZOOMS,&temp,0);

  // Another method for adding bitmaps to menu options is through the
  // LoadToolbars member function.This method allows you to add all
  // the bitmaps in a toolbar object to menu options (if they exist).
  // The first function parameter is an array of toolbar id's.
  // The second is the number of toolbar id's. There is also a
  // function called LoadToolbar that just takes an id.
  m_menu.LoadToolbars(toolbars,2);

  return(m_menu.Detach());
}

HMENU CMainFrame::NewMyMenu()
{
  static UINT toolbars[]={
    IDR_MAINFRAME,
    IDR_TOOLBAR
  };

  m_mymenu.LoadMenu(IDR_MYTYPE);
  m_mymenu.LoadToolbars(toolbars,2);

  return(m_mymenu.Detach());
}

HMENU CMainFrame::NewDefaultMenu()
{
  m_default.LoadMenu(IDR_MAINFRAME);
  m_default.LoadToolbar(IDR_MAINFRAME);
  return(m_default.Detach());
}

void CMainFrame::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
  pCmdUI->SetCheck(Undocheck);
}


void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{
  BOOL setflag=FALSE;
  if(lpMeasureItemStruct->CtlType==ODT_MENU){
    if(IsMenu((HMENU)lpMeasureItemStruct->itemID)&&BCMenu::IsMenu((HMENU)lpMeasureItemStruct->itemID)){
      m_menu.MeasureItem(lpMeasureItemStruct);
      setflag=TRUE;
    }
  }
	if(!setflag)CMDIFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}


LRESULT CMainFrame::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) 
{
  LRESULT lresult;
  if(BCMenu::IsMenu(pMenu))
    lresult=BCMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
	else
    lresult=CMDIFrameWnd::OnMenuChar(nChar, nFlags, pMenu);
  return(lresult);
}

void CMainFrame::OnEditCopy() 
{
}

void CMainFrame::OnEditCut() 
{
}

void CMainFrame::OnEditPaste() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnUpdateZoom(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(zoomcheck);
}

void CMainFrame::OnDefault() 
{
  CMenu *menu = AfxGetMainWnd()->GetMenu()->GetSubMenu(2);
  if(::GetMenuDefaultItem(menu->m_hMenu,MF_BYPOSITION,0)==3)
    ::SetMenuDefaultItem(menu->m_hMenu,(unsigned int)-1,MF_BYPOSITION);//SK: removed  warning C4245: 'argument' : conversion from 'const int' to 'unsigned int', signed/unsigned mismatch
  else
    ::SetMenuDefaultItem(menu->m_hMenu,3,MF_BYPOSITION);
}

void CMainFrame::OnUpdateDefault(CCmdUI* pCmdUI) 
{
  CMenu *menu = AfxGetMainWnd()->GetMenu()->GetSubMenu(2);
  if(::GetMenuDefaultItem(menu->m_hMenu,MF_BYPOSITION,0)==3){
    pCmdUI->SetRadio(TRUE);
    pCmdUI->SetText(_T("Default ON"));//SK modified for Unicode
  }
  else{
    pCmdUI->SetRadio(FALSE);
    pCmdUI->SetText(_T("Default"));//SK modified for Unicode
  }
}

void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
{
	CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

  if(!bSysMenu){
    if(BCMenu::IsMenu(pPopupMenu)) BCMenu::UpdateMenu(pPopupMenu);
  }
}

void CMainFrame::OnHomepage() 
{
  ShellExecute(::GetDesktopWindow(),_T("open"),//SK modified for Unicode
    _T("http://www.rocscience.com/~corkum/BCMenu.html"),NULL,NULL,//SK modified for Unicode
    SW_MAXIMIZE);
}

void CMainFrame::OnEnable() 
{
 disable_flag=!disable_flag;
}

void CMainFrame::OnUpdateEnable(CCmdUI* pCmdUI) 
{
  pCmdUI->Enable(!disable_flag);
  if(!disable_flag)pCmdUI->SetText(_T("&Enabled"));//SK modified for Unicode
  else pCmdUI->SetText(_T("&Disabled"));//SK modified for Unicode
}

void CMainFrame::OnDisable() 
{
 disable_flag=!disable_flag;
}

void CMainFrame::OnUpdateDisable(CCmdUI* pCmdUI) 
{
  pCmdUI->Enable(disable_flag);
  if(disable_flag)pCmdUI->SetText(_T("&Enabled"));//SK modified for Unicode
  else pCmdUI->SetText(_T("&Disabled"));//SK modified for Unicode
}

void CMainFrame::OnAddMenuOptions() 
{
  BCMenu *menu = (BCMenu *)AfxGetMainWnd()->GetMenu()->GetSubMenu(1);
  int numitems=menu->GetMenuItemCount();
  if((zoomflag&&numitems==7)||(!zoomflag&&numitems==4)){

//  There are 2 ways of doing the dynamic popups

//  This is method 1 (using AppendMenu with MF_POPUP)
//    menu->AppendMenu(MF_STRING,ID_EDIT_CUT,_T("Cu&t\tCtrl+X"));
//    BCMenu *popup1=new BCMenu; // deleted in BCMenu::RemoveMenu
//    popup1->CreatePopupMenu();
//    popup1->AppendMenu(MF_STRING,ID_EDIT_PASTE,_T("&Paste\tCtrl+V"));
//    BCMenu *popup2=new BCMenu; // deleted in BCMenu::RemoveMenu
//    popup2->CreatePopupMenu();
//    popup2->AppendMenu(MF_STRING,ID_EDIT_COPY,_T("&Copy\tCtrl+C"));
//    popup1->AppendMenu(MF_POPUP,(UINT)popup2->m_hMenu,_T("Pop&up2"));
//    menu->AppendMenu(MF_POPUP,(UINT)popup1->m_hMenu,_T("P&opup1"));

//  This is method 2 (using AppendODPopupMenu). AppendODPopupMenu
//  has the added advantage of using the current BCMenu's properties.
//  (i.e. check mark type etc.)
    menu->AppendMenu(MF_STRING,ID_EDIT_CUT,_T("Cu&t\tCtrl+X"));
    BCMenu *popup1=menu->AppendODPopupMenu(_T("P&opup1"));
    popup1->AppendMenu(MF_STRING,ID_EDIT_PASTE,_T("&Paste\tCtrl+V"));
    BCMenu *popup2=popup1->AppendODPopupMenu(_T("Pop&up2"));
    popup2->AppendMenu(MF_STRING,ID_EDIT_COPY,_T("&Copy\tCtrl+C"));

//  Add the bitmaps to the new menu's
    menu->LoadToolbar(IDR_MAINFRAME); 
    menu->ModifyODMenu(NULL,_T("Pop&up2"),IDB_NET);
  }
  else{
    int count = zoomflag ? 7 : 4;
// call BCMenu::RemoveMenu to remove the dynamic menu's. Note that
// the function also delete's the BCMenu object so don't call delete.
    for(int i=numitems;i>=count;--i)menu->RemoveMenu(i,MF_BYPOSITION);
  }
}

void CMainFrame::OnUpdateAddMenuOptions(CCmdUI* pCmdUI) 
{
  CMenu *menu = AfxGetMainWnd()->GetMenu()->GetSubMenu(1);
  int numitems=menu->GetMenuItemCount();
  if((zoomflag&&numitems==7)||(!zoomflag&&numitems==4))pCmdUI->SetCheck(FALSE);
  else pCmdUI->SetCheck(TRUE);
}

void CMainFrame::OnRemoveZoom() 
{
  BCMenu *menu = (BCMenu *)AfxGetMainWnd()->GetMenu()->GetSubMenu(1);
  int numitems=menu->GetMenuItemCount();
  if(numitems==7||numitems==9){
    menu->RemoveMenu(0,MF_BYPOSITION);
    menu->RemoveMenu(0,MF_BYPOSITION);
    menu->RemoveMenu(0,MF_BYPOSITION);
    zoomflag=FALSE;
  }
}

void CMainFrame::OnMenu2() 
{
  menu2flag=!menu2flag;
  BCMenu *pMenu = (BCMenu *)AfxGetMainWnd()->GetMenu()->GetSubMenu(3);
  int numitems=pMenu->GetMenuItemCount();
  for(int i=numitems-1;i>=0;--i)pMenu->DeleteMenu(i,MF_BYPOSITION);
  if(menu2flag){
    pMenu->AppendMenu(MF_STRING,ID_NEW,_T("New"));
    pMenu->AppendMenu(MF_STRING,ID_TILE,_T("Tile"));
    BCMenu *popup1=pMenu->AppendODPopupMenu(_T("P&opup1"));
    popup1->AppendMenu(MF_STRING,ID_EDIT_PASTE,_T("&Paste\tCtrl+V"));
    pMenu->LoadToolbar(IDR_TOOLBAR);
    pMenu->LoadToolbar(IDR_MAINFRAME); 
  }
  else{
    pMenu->AppendMenu(MF_STRING,ID_ZOOMS,_T("Zoom"),IDB_ZOOM);

  	CImageList temp;
    temp.Create(16,15,ILC_COLORDDB|ILC_MASK,1,1);
	  pMenu->AddBitmapToImageList(&temp,IDB_NET);
    pMenu->InsertMenu(0,MF_STRING|MF_BYPOSITION,ID_NET,_T("Net"),&temp,0);
  }
}

void CMainFrame::OnUpdateMenu2(CCmdUI* pCmdUI) 
{
  if(!menu2flag)pCmdUI->SetCheck(FALSE);
  else pCmdUI->SetCheck(TRUE);
}

void CMainFrame::OnZooms() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnNew() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnTile() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnJunk() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnNet() 
{
	// TODO: Add your command handler code here
	
}

void CMainFrame::OnNewDocTemplate() 
{
  CMDIFrameWnd *pFrame=(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
  CMDIChildWnd *pChild=(CMDIChildWnd *)pFrame->GetActiveFrame();
 	CMymenuDoc* pDoc = (CMymenuDoc *)pChild->GetActiveDocument();
  CMymenuApp *pApp  = (CMymenuApp *)AfxGetApp();
  CMultiDocTemplate *pTemplate=pApp->pMyTemplate;
  if(pDoc&&pApp&&pTemplate){
    CMyFrame *pNewFrame = (CMyFrame *)pTemplate->CreateNewFrame(pDoc,NULL);
    if(pNewFrame)pTemplate->InitialUpdateFrame(pNewFrame,pDoc);
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Web Developer
Canada Canada
I'm the senior software development manager for Rocscience Inc., a company specializing in geomechanics software. I have a PH.D in Civil Engineering, and have been programming since 1978. I've used more computers and languages then 2000 characters lets me list. Besides programming, I enjoy golfing, watching my 3 kids play sports, spending time with my wife, and watching plenty of hockey and football.

Comments and Discussions