www.gusucode.com > VC++简单医学图像处理系统源码程序 > VC++简单医学图像处理系统源码程序/code/MenuEx.cpp

    //Download by http://www.NewXing.com
#include "stdafx.h"
#include "MenuEx.h"

IMPLEMENT_DYNAMIC( CMenuEx, CMenu )

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMenuEx::CMenuEx()
{
	m_bPopupMenu=FALSE;					// initialize this menu flag
										// FALSE indicate this menu is top-level menu
										// TRUE means this menu is popupmenu

	m_nSeparator = 10;					// separator menu item 's height

	// initialize color attribute
	m_crBackground = ::GetSysColor(COLOR_MENU);	
	m_crText =::GetSysColor(COLOR_MENUTEXT);
	m_crTextSelected =::GetSysColor(COLOR_MENUTEXT);
	m_crLeft=RGB(236,233,216);
	m_crSelectedBroder=RGB(49,106,197);
	m_crSelectedFill=RGB(200,220,253);

	// no normal imagelist
	m_pImageList=NULL;					
	m_pDisabledImageList=NULL;			
	m_pHotImageList=NULL;		
	
	// default menu image size
	m_szImage=CSize(20,20);				
}
/////////////////////////////////////////////////////////////////////////////
CMenuEx::~CMenuEx()
{	
	// destroy menu and free all variable
	DestroyMenu();	
}
/////////////////////////////////////////////////////////////////////////////

BOOL CMenuEx::DestroyMenu()
{	
	// delete all imagelist
	if(m_pImageList!=NULL)
		m_pImageList->DeleteImageList();

	if(m_pDisabledImageList!=NULL)
		m_pDisabledImageList->DeleteImageList();

	if(m_pHotImageList!=NULL)
		m_pHotImageList->DeleteImageList();		


	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		MENUITEM *pMenuItem = m_MenuItemArr.GetAt(i);
		
		// destroy submenu
		if(pMenuItem->bIsSubMenu)
			pMenuItem->pSubMenu->DestroyMenu(); 		
		
		// remove menu item from array
		m_MenuItemArr.RemoveAt(i);
		
		// free menuitem struct
		delete pMenuItem;
	}	
	return CMenu::DestroyMenu();
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::LoadMenu(UINT nIDResource)
{
	// load menu from menu editor created resouce
	CMenu Menu;
	Menu.LoadMenu(nIDResource);

	// empty all variable
	if(m_hMenu!=NULL)	
		DestroyMenu();	
		
	if(m_bPopupMenu)
	{
		// create popupmenu
		if(!CreatePopupMenu()) 
			return FALSE;	
	}
	else
	{
		// create top-level menu  
		if(!CreateMenu()) 
			return FALSE; 
	}		
	return LoadMenu(Menu);
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::LoadMenu(HMENU hMenu)
{
	// load menu from global HMENU handle
	CMenu Menu;
	Menu.Attach(hMenu);
	
	// empty all variable
	if(m_hMenu!=NULL)	
		DestroyMenu();	
	
	if(m_bPopupMenu)
	{
		// create popupmenu
		if(!CreatePopupMenu()) 
			return FALSE;	
	}
	else
	{
		// create top-level menu  
		if(!CreateMenu()) 
			return FALSE; 
	}	
	return LoadMenu(Menu);
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::LoadMenu(LPCTSTR lpszResourceName)
{
	// load menu from resource string
	CMenu Menu;
	Menu.LoadMenu(lpszResourceName);
	
	// empty all variable
	if(m_hMenu!=NULL)	
		DestroyMenu();	
	
	if(m_bPopupMenu)
	{
		// create popupmenu
		if(!CreatePopupMenu()) 
			return FALSE;	
	}
	else
	{
		// create top-level menu  
		if(!CreateMenu()) 
			return FALSE; 
	}	
	return LoadMenu(Menu);
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::LoadMenu(CMenu& Menu)
{	
	UINT nID;
	UINT nIndex;	
	UINT nState;
	CString strMenu;

	// fill this menu use temp menu
	for(nIndex = 0; nIndex < Menu.GetMenuItemCount(); nIndex++)
	{		
		nID=Menu.GetMenuItemID(nIndex);					// get menu ID
		nState=Menu.GetMenuState(nIndex,MF_BYPOSITION);	// get menu state
		Menu.GetMenuString(nIndex,strMenu,MF_BYPOSITION);// get menu name
		
		if(nID==0)
		{	
			// insert separator
			if(!AppendMenu(MF_SEPARATOR))
				return FALSE;
		}
		else if(nID==-1)
		{
			// bypass popupmenu's item number	
			nState&=0x00FFL;	
			
			// insert popupmenu
			if(!AppendMenu(MF_POPUP|nState,(UINT)Menu.GetSubMenu(nIndex)->Detach(),strMenu))
				return FALSE;
		}
		else
		{		
			// insert normal menu item
			if(!AppendMenu(MF_STRING|nState,nID,strMenu))
				return FALSE;
		}
	}		
	return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem )
{	
	// append ownerdrawn style menu item to this menu
	// get last position of this menu
	UINT nIndex=m_MenuItemArr.GetSize();
	
	// insert menu item to last position
	// means append menu item
	return InsertMenu(nIndex,nFlags|MF_BYPOSITION,nIDNewItem,lpszNewItem);	
}

/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem , LPCTSTR lpszNewItem )
{
	// insert menu item to specific position or command ID
	LPMENUITEM pMenuItem;
	UINT nIndex;
	CSize  size;	
	
	// mainframe's device context,use to get text size
	CDC	 *pDC =AfxGetMainWnd()->GetDC();

	if(nFlags & MF_BYPOSITION)
	{
		// insert menu item by position
		pMenuItem=new MENUITEM;

		if(nFlags&MF_SEPARATOR)
		{
			// insert separator
			pMenuItem->strText = "";						// no name
			pMenuItem->nID = 0;								// separator's ID
			pMenuItem->itemSize=CSize(0,m_nSeparator);		// separator's default size
			pMenuItem->pImageList=NULL;						// separator has no image
			pMenuItem->pDisabledImageList=NULL;
			pMenuItem->pHotImageList=NULL;
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=FALSE;					// separator must not be popupmenu
			pMenuItem->pSubMenu=NULL;				
			
			// insert menu item to this menu
			if(!CMenu::InsertMenu(nPosition,nFlags,nIDNewItem,lpszNewItem))
			{
				delete pMenuItem;
				AfxGetMainWnd()->ReleaseDC(pDC);
				return FALSE;
			}
			
			if(m_bPopupMenu)
			{			
				// modify menu item to ownerdrawn style
				// if this menu is not a top-level menu
				if(!CMenu::ModifyMenu(nPosition,MF_SEPARATOR|MF_BYPOSITION|MF_OWNERDRAW,0,(LPCTSTR)pMenuItem))
				{
					delete pMenuItem;
					AfxGetMainWnd()->ReleaseDC(pDC);
					return FALSE;
				}
			}			
			// insert menu item to array
			m_MenuItemArr.InsertAt(nPosition,pMenuItem);
		}
		else if(nFlags&MF_POPUP)
		{
			// insert popupmenu
			CMenuEx* pSubMenu=new CMenuEx;

			// create new popupmenu
			pSubMenu->SetPopupMenu(TRUE);

			// load popupmenu from specific handle
			pSubMenu->LoadMenu((HMENU)nIDNewItem);
			size=pDC->GetTextExtent(lpszNewItem);

			pMenuItem->strText = lpszNewItem;
			pMenuItem->nID = -1;	
			
			// specified menu item size,do not include image's size
			pMenuItem->itemSize.cx=size.cx+25;
			pMenuItem->itemSize.cy=2;
			
			// specified all imagelist for new menu item
			pMenuItem->pImageList=m_pImageList;		
			pMenuItem->pDisabledImageList=m_pDisabledImageList;
			pMenuItem->pHotImageList=m_pHotImageList;
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=TRUE;
			pMenuItem->pSubMenu=pSubMenu;		// popupmenu's pointor				
			
			if(!CMenu::InsertMenu(nPosition,nFlags,(UINT)(pSubMenu->m_hMenu),lpszNewItem))
			{
				delete pMenuItem;
				AfxGetMainWnd()->ReleaseDC(pDC);
				return FALSE;
			}
			
			if(m_bPopupMenu)
			{			
				if(!CMenu::ModifyMenu(nPosition,nFlags|MF_POPUP|MF_BYPOSITION|MF_OWNERDRAW,(UINT)(pSubMenu->m_hMenu),(LPCTSTR)pMenuItem))
				{
					delete pMenuItem;
					AfxGetMainWnd()->ReleaseDC(pDC);
					return FALSE;
				}
			}			
			m_MenuItemArr.InsertAt(nPosition,pMenuItem);
		}
		else // if(nFlags & MF_STRING)
		{
			// insert normal menu item
			size=pDC->GetTextExtent(lpszNewItem);

			pMenuItem->strText = lpszNewItem;
			pMenuItem->nID = nIDNewItem;			
			pMenuItem->itemSize.cx=size.cx+10;
			pMenuItem->itemSize.cy=2;		
			pMenuItem->pImageList=m_pImageList;		
			pMenuItem->pDisabledImageList=m_pDisabledImageList;
			pMenuItem->pHotImageList=m_pHotImageList;
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=FALSE;
			pMenuItem->pSubMenu=NULL;					
			
			if(!CMenu::InsertMenu(nPosition,nFlags,nIDNewItem,lpszNewItem))
			{
				delete pMenuItem;
				AfxGetMainWnd()->ReleaseDC(pDC);
				return FALSE;
			}			
			if(m_bPopupMenu)
			{			
				if(!CMenu::ModifyMenu(nPosition,MF_BYPOSITION|MF_OWNERDRAW,nIDNewItem,(LPCTSTR)pMenuItem))
				{
					delete pMenuItem;
					AfxGetMainWnd()->ReleaseDC(pDC);
					return FALSE;
				}
			}
			m_MenuItemArr.InsertAt(nPosition,pMenuItem);
		}			
		return TRUE;
	}
	else if(nFlags & MF_BYCOMMAND)		// insert menu item by command ID
	{		
		for(nIndex = 0; nIndex < (UINT)m_MenuItemArr.GetSize(); nIndex++)
		{
			pMenuItem=m_MenuItemArr.GetAt(nIndex);
			
			// insert menu item with position
			// if the position match command ID
			if(pMenuItem->nID == nPosition)
				return InsertMenu(nIndex,MF_BYPOSITION,nIDNewItem,lpszNewItem);					
		}

		// do not found menu item in this menu
		CMenuEx* pSubMenu=FindPopupMenuFromID(nPosition);

		if(pSubMenu==NULL)
		{
			// not found 
			AfxGetMainWnd()->ReleaseDC(pDC);
			return FALSE;
		}
		else
		{
			// insert menu item to submenu
			return pSubMenu->InsertMenu(nPosition,nFlags,nIDNewItem ,lpszNewItem);
		}		
	}	

	AfxGetMainWnd()->ReleaseDC(pDC);
	return FALSE;
}
/////////////////////////////////////////////////////////////////////////////

BOOL CMenuEx::RemoveMenu(UINT nPosition, UINT nFlags)
{	
	UINT nIndex;
	LPMENUITEM pMenuItem;

	// remove menu item by position
	if(nFlags & MF_BYPOSITION)
	{
		// position out of range of menu item array
		if(nPosition>(UINT)(m_MenuItemArr.GetSize()-1))
			return FALSE;

		// remove menu item from menu item array
		m_MenuItemArr.RemoveAt(nPosition);
				
		// remvoe menu item from this menu
		if(!CMenu::RemoveMenu(nPosition,nFlags))
			return FALSE;
	}
	else if(nFlags & MF_BYCOMMAND)
	{
		// remove menu item by command ID
		for(nIndex = 0; nIndex < (UINT)m_MenuItemArr.GetSize(); nIndex++)
		{
			pMenuItem = m_MenuItemArr.GetAt(nIndex);
			
			// remove menu item by position match command ID
			if(pMenuItem->nID == nPosition)			
				return RemoveMenu(nIndex,MF_BYPOSITION);						
		}	
		
		// found menu item from submenu of this menu
		CMenuEx* pSubMenu=FindPopupMenuFromID(nPosition);		
		if(pSubMenu==NULL)					
			return FALSE;		// not found
		else
			return pSubMenu->RemoveMenu(nIndex,MF_BYPOSITION);	// remove menu item from submenu		
	}
	
	return FALSE;	
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMenuEx::ModifyMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem)
{
	UINT nIndex;
	LPMENUITEM pMenuItem;
	CDC	 *pDC =AfxGetMainWnd()->GetDC();	
	CSize  size;

	// modify menu item by position
	if(nFlags & MF_BYPOSITION)
	{
		if(!CMenu::ModifyMenu(nPosition,nFlags,nIDNewItem,lpszNewItem))
		{	
			// fail to modify menu
			AfxGetMainWnd()->ReleaseDC(pDC);
			return FALSE;
		}				
		pMenuItem=GetMenuItem(nPosition);
		
		if(pMenuItem==NULL)
			return FALSE;

		if(nFlags&MF_SEPARATOR)
		{
			// modify menu item to separator
			pMenuItem->strText = "";
			pMenuItem->nID = 0;		
			pMenuItem->itemSize=CSize(0,m_nSeparator);
			pMenuItem->pImageList=m_pImageList;		
			pMenuItem->pDisabledImageList=m_pDisabledImageList;
			pMenuItem->pHotImageList=m_pHotImageList;
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=FALSE;
			pMenuItem->pSubMenu=NULL;			
		}
		else if(nFlags&MF_POPUP)
		{
			// modify menu item to popupmenu item
			CMenuEx* pSubMenu=new CMenuEx;
			pSubMenu->SetPopupMenu(TRUE);
			pSubMenu->LoadMenu((HMENU)nIDNewItem);

			pMenuItem->strText = lpszNewItem;
			pMenuItem->nID = -1;
			size=pDC->GetTextExtent(lpszNewItem);
			pMenuItem->itemSize.cx=size.cx+25;
			pMenuItem->itemSize.cy=2;		
			pMenuItem->pImageList=m_pImageList;		
			pMenuItem->pDisabledImageList=m_pDisabledImageList;
			pMenuItem->pHotImageList=m_pHotImageList;
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=TRUE;
			pMenuItem->pSubMenu=pSubMenu;					
		}
		else // MF_STRING
		{
			// modify menu item to normal menu item
			pMenuItem->strText = lpszNewItem;
			pMenuItem->nID = nIDNewItem;

			size=pDC->GetTextExtent(lpszNewItem);
			pMenuItem->itemSize.cx=size.cx+10;
			pMenuItem->itemSize.cy=2;	
			pMenuItem->pImageList=m_pImageList;		
			pMenuItem->pDisabledImageList=m_pDisabledImageList;
			pMenuItem->pHotImageList=m_pHotImageList;			
			pMenuItem->nImageIndex=-1;
			pMenuItem->bIsSubMenu=FALSE;
			pMenuItem->pSubMenu=NULL;			
		}			
		return TRUE;		
	}
	else if(nFlags & MF_BYCOMMAND)
	{
		// modify menu item by command ID
		for(nIndex = 0; nIndex < (UINT)m_MenuItemArr.GetSize(); nIndex++)
		{
			pMenuItem=m_MenuItemArr.GetAt(nIndex);	
			
			// modify ID matched menu item by position
			if(pMenuItem->nID == nPosition)						
				return ModifyMenu(nIndex,MF_BYPOSITION,nIDNewItem,lpszNewItem);							
		}
		
		// walk through all items, looking for ID matched popupmenu
		CMenuEx* pSubMenu=FindPopupMenuFromID(nPosition);
		
		if(pSubMenu==NULL)					
			return FALSE;		// not found	
		else		
			return pSubMenu->ModifyMenu(nPosition,nFlags,nIDNewItem,lpszNewItem);			
	}		
	return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
CMenuEx* CMenuEx::GetSubMenu(int nPosition)
{
	// get submenu by position based zero
	// return NULL if do not exist
	if((UINT)nPosition>(m_MenuItemArr.GetSize()-1))
		return NULL;
	
	return m_MenuItemArr.GetAt(nPosition)->pSubMenu;
}
/////////////////////////////////////////////////////////////////////////////
CMenuEx* CMenuEx::FindPopupMenuFromID(UINT nID)
{
	ASSERT_VALID(this);
	
	// walk through all items, looking for ID match
	UINT nItems = GetMenuItemSize();
	for (int iItem = 0; iItem < (int)nItems; iItem++)
	{
		CMenuEx* pPopup = GetSubMenu(iItem);
		if (pPopup != NULL)
		{
			// recurse to child popup
			pPopup = FindPopupMenuFromID(nID);
			// check popups on this popup
			if (pPopup != NULL)
				return pPopup;
		}
		else if (GetMenuItemID(iItem) == nID)
		{
			// it is a normal item inside this popup			
			return this;
		}
	}
	// not found
	return NULL;
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	// chech this is ownerdrawn menu or not
	if(lpDIS->CtlType!=ODT_MENU)
		return;	

	// drawn device context for draw menu
	CDC* pDC=CDC::FromHandle(lpDIS->hDC);
	LPMENUITEM lpMenuItem=(LPMENUITEM)lpDIS->itemData;

	// rect region of device context
	CRect rect=CRect(lpDIS->rcItem);	
	
	// draw background of menu item
	DrawBackground(pDC,rect);	
	
	// draw selected 	
	DrawSelected(pDC,rect,lpDIS);		
	
	// draw menu text
	DrawMenuText(pDC,rect,lpDIS);
	
	//draw menu imagelist
	DrawMenuImage(pDC,rect,lpDIS);		
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::DrawBackground(CDC* pDC,CRect rect)
{
	CBrush BGBrush(m_crBackground);
	CBrush LeftBrush(m_crLeft);
	CRect rcLeft=rect;	

	rcLeft.right = rcLeft.left+m_szImage.cx+2;
	
	pDC->FillRect(rect,&BGBrush);
	pDC->FillRect(rcLeft,&LeftBrush);
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::DrawMenuImage(CDC *pDC, CRect rect,LPDRAWITEMSTRUCT lpDIS)
{
	CRect rcImage=rect;
	LPMENUITEM lpMenuItem=(LPMENUITEM)lpDIS->itemData;
	
	rcImage.left+=1;
	rcImage.right=rcImage.left+m_szImage.cx;

	rcImage.top+=1;
	rcImage.bottom=rcImage.top+m_szImage.cy;	

	// menu item style is checked
	// draw "√" instead of image
	if(lpDIS->itemState & ODS_CHECKED)
	{	
		CString check("√");
		CPen* pBorderPen=new CPen(PS_SOLID,1,m_crSelectedBroder);
		CBrush* pFillBrush=new CBrush(m_crSelectedFill);
		CPen* pOldPen= pDC->SelectObject(pBorderPen);
		CBrush* pOldBrush= pDC->SelectObject(pFillBrush);
	
		pDC->Rectangle(rcImage);		
		pDC->SelectObject(pOldPen);
		pDC->SelectObject(pOldBrush);
		
		CSize size=pDC->GetTextExtent(check);
		rcImage.left=rcImage.left+(rcImage.Width()-size.cx)/2;
		rcImage.top=rcImage.top+(rcImage.Height()-size.cy)/2-4;

		pDC->SetBkMode(TRANSPARENT);

		if(lpDIS->itemState & ODS_GRAYED)
		{	
			// draw grayed "√"
			pDC->DrawState(rcImage.TopLeft(), rcImage.Size(),check, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
		}
		else
		{	
			// set text color for different text style
			if(lpDIS->itemState & ODS_SELECTED)			
				pDC->SetTextColor(m_crTextSelected);			
			else			
				pDC->SetTextColor(m_crText);
			
			// draw normal "√"
			pDC->DrawText(check,rcImage,DT_EXPANDTABS|DT_VCENTER|DT_SINGLELINE);
		}		
		pDC->SetBkMode(OPAQUE);
	}
	else
	{
		// draw imagelist of menu item
		// if menu item has image(nImageIndex!=-1)
		if(lpMenuItem->nImageIndex !=-1)
		{			
			CImageList* pImageList=lpMenuItem->pImageList;			
			
			if((lpDIS->itemState&ODS_GRAYED)&&(lpMenuItem->pDisabledImageList!=NULL))
			{
				// draw disabled image
				pImageList=lpMenuItem->pDisabledImageList;
			}
			else if((lpDIS->itemState&ODS_SELECTED)&&(lpMenuItem->pHotImageList!=NULL))
			{	
				// draw selected image
				pImageList=lpMenuItem->pHotImageList;
			}							
			
			// draw NO.nImageIndex image of imagelist
			pImageList->Draw(pDC,lpMenuItem->nImageIndex,rcImage.TopLeft(),ILD_TRANSPARENT);		
		}
	}	
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::DrawMenuText(CDC *pDC, CRect rect,LPDRAWITEMSTRUCT lpDIS)
{
	CRect rcText=rect;
	LPMENUITEM lpMenuItem=(LPMENUITEM)lpDIS->itemData;	
	rcText.left = rcText.left+m_szImage.cx+2+8;	
	
	// not use background color when draw text
	pDC->SetBkMode(TRANSPARENT);
	
	if(lpMenuItem->nID==0)
	{
		// draw separator
		rcText.top =rcText.Height()/2+rcText.top-1;
		rcText.bottom =rcText.top +1;
		pDC->FillSolidRect(rcText,RGB(197,194,184));		
	}
	else
	{	
		// calculate text position
		CSize size=pDC->GetTextExtent(lpMenuItem->strText);		
		rcText.top=rcText.top+(rcText.Height()-size.cy)/2;

		if(lpDIS->itemState & ODS_GRAYED)
		{	
			// draw grayed text
			pDC->DrawState(rcText.TopLeft(), rcText.Size(), lpMenuItem->strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
		}
		else
		{
			// set text color
			if(lpDIS->itemState & ODS_SELECTED)			
				pDC->SetTextColor(m_crTextSelected);			
			else			
				pDC->SetTextColor(m_crText);				
			
			// draw normal text
			pDC->DrawText(lpMenuItem->strText,rcText,DT_LEFT | DT_EXPANDTABS | DT_VCENTER);
		}
	}	
	pDC->SetBkMode(OPAQUE);
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::DrawSelected(CDC *pDC, CRect rect,LPDRAWITEMSTRUCT lpDIS)
{
	CRect rcText=rect;
	LPMENUITEM lpMenuItem=(LPMENUITEM)lpDIS->itemData;

	// separator,grayed menu item,disabled menu item
	// can not be selected
	if((lpMenuItem->nID==0)||(lpDIS->itemState & ODS_GRAYED)||(lpDIS->itemState & ODS_DISABLED))
		return;	
	// draw selected recatangle use special color
	// if current menu item is selected
	if(lpDIS->itemState & ODS_SELECTED )
	{
		CPen* pBorderPen=new CPen(PS_SOLID,1,m_crSelectedBroder);
		CBrush* pFillBrush=new CBrush(m_crSelectedFill);		
		CPen* pOldPen= pDC->SelectObject(pBorderPen);
		CBrush* pOldBrush= pDC->SelectObject(pFillBrush);
		
		pDC->Rectangle(rect);		// draw selected rectangle

		pDC->SelectObject(pOldPen);
		pDC->SelectObject(pOldBrush);
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetImageList(CImageList* pImageList)
{
	if(pImageList==NULL)
		return;		

	IMAGEINFO info;
	LPMENUITEM lpMenuItem;	
	m_pImageList =pImageList;
	
	// get imagelist size
	pImageList->GetImageInfo(0,&info);	
	m_szImage.cx=info.rcImage.right-info.rcImage.left;	
	m_szImage.cy=info.rcImage.bottom-info.rcImage.top;

	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);

		// set normal imagelist for menu item
		lpMenuItem->pImageList=pImageList;
		
		// set submenu imagelist
		if(lpMenuItem->bIsSubMenu)		
			lpMenuItem->pSubMenu->SetImageList(pImageList);				
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetDisabledImageList(CImageList* pImageList)
{
	if(pImageList==NULL)
		return;
	
	LPMENUITEM lpMenuItem;
	// update disabled imagelist
	m_pDisabledImageList =pImageList;
	
	if(m_pImageList==NULL&&m_pHotImageList==NULL)
	{		
		IMAGEINFO info;
		
		// only set disabled imagelist
		// get imagelist size
		pImageList->GetImageInfo(0,&info);		
		m_szImage.cx=info.rcImage.right-info.rcImage.left;	
		m_szImage.cy=info.rcImage.bottom-info.rcImage.top;
	}
	
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		lpMenuItem->pDisabledImageList=pImageList;
		
		// set submenu disabled imagelis
		if(lpMenuItem->bIsSubMenu)		
			lpMenuItem->pSubMenu->SetDisabledImageList(pImageList);
				
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetHotImageList(CImageList* pImageList)
{
	if(pImageList==NULL)
		return;
	
	LPMENUITEM lpMenuItem;
	m_pHotImageList =pImageList;
	
	if(m_pImageList==NULL&&m_pDisabledImageList==NULL)
	{		
		IMAGEINFO info;		

		// only hot imagelist is set
		// get imagelist size
		pImageList->GetImageInfo(0,&info);			
		m_szImage.cx=info.rcImage.right-info.rcImage.left;	
		m_szImage.cy=info.rcImage.bottom-info.rcImage.top;
	}

	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		lpMenuItem->pHotImageList=pImageList;
		
		// set submenu hot imagelis
		if(lpMenuItem->bIsSubMenu)		
			lpMenuItem->pSubMenu->SetHotImageList(pImageList);		
	}	
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetImageIndex(const UINT* nIDResource,UINT nIDCount)
{
	// set imagelist index from specific table "nIDResource[nIDCount]"
	// only can SetImageIndex after set one imagelist
	if(m_pImageList==NULL&&m_pHotImageList==NULL&&m_pDisabledImageList==NULL)
		return;

	LPMENUITEM lpMenuItem;
	for(UINT nIndex=0;nIndex<(UINT)m_MenuItemArr.GetSize();nIndex++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(nIndex);

		// call submenu 's loadtoolbar
		if(lpMenuItem->bIsSubMenu)		
			lpMenuItem->pSubMenu->SetImageIndex(nIDResource,nIDCount);		
		else
		{
			for(UINT i=0;i<nIDCount;i++)
			{
				// if table's commandID equal menu item's command ID
				// set nImageIndex to table's index
				if(lpMenuItem->nID==nIDResource[i])
					lpMenuItem->nImageIndex=i;
			}
		}
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::LoadToolBar(const CToolBar* pToolBar)
{
	
	// load all imagelist from pToolBar
	SetImageList(pToolBar->GetToolBarCtrl().GetImageList());
	SetDisabledImageList(pToolBar->GetToolBarCtrl().GetDisabledImageList());
	SetHotImageList(pToolBar->GetToolBarCtrl().GetHotImageList());
	
	// pToolBar don't have imagelist
	if(m_pImageList==NULL&&m_pDisabledImageList==NULL&&m_pHotImageList==NULL)
		return;

	LPMENUITEM pItem;

	for(UINT nIndex=0;nIndex<(UINT)m_MenuItemArr.GetSize();nIndex++)
	{
		pItem=m_MenuItemArr.GetAt(nIndex);		
		
		// load submenu toolbar
		if(pItem->bIsSubMenu)		
			pItem->pSubMenu->LoadToolBar(pToolBar);		
		else
		{	
			for(UINT i=0;i<(UINT)pToolBar->GetToolBarCtrl().GetButtonCount();i++)
			{				 
				if(pItem->nID==pToolBar->GetItemID(i))
				{
					// if toolbar's commandID equal menu item's command ID
					// set nImageIndex to toolbar's index
					pItem->nImageIndex=i;

					// set all imagelist to toolbar's imagelist
					pItem->pImageList=m_pImageList;
					pItem->pDisabledImageList=m_pDisabledImageList;
					pItem->pHotImageList=m_pHotImageList;						
				}
			}
		}		
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetTextColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set normal menu text color
	m_crText =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		
		// set submenu text color
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetTextColor(color);
	}
}
/////////////////////////////////////////////////////////////////////////////

void CMenuEx::SetBackgroundColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set menu background color
	m_crBackground =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetBackgroundColor(color);
	}
}
/////////////////////////////////////////////////////////////////////////////

void CMenuEx::SetTextSelectedColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set selected menu text color
	m_crTextSelected =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetTextSelectedColor(color);	
	}
}
/////////////////////////////////////////////////////////////////////////////

void CMenuEx::SetLeftColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set menu left side color
	m_crLeft =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetLeftColor(color);
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetSelectedBroderColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set selected rectangle border color
	m_crSelectedBroder =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetSelectedBroderColor(color);
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetSelectedFillColor(COLORREF color)
{
	LPMENUITEM lpMenuItem;
	// set selected rectangle fill color
	m_crSelectedFill =color;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		lpMenuItem=m_MenuItemArr.GetAt(i);
		if(lpMenuItem->bIsSubMenu)
			lpMenuItem->pSubMenu->SetSelectedFillColor(color);
	}
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::SetPopupMenu(BOOL bPopupMenu)
{
	// set top-level menu indicator	
	m_bPopupMenu=bPopupMenu;
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::UpdatePopupMenu()
{	
	// top-level menu do not need update popupmenu
	if(!m_bPopupMenu)
		return;
	
	LPMENUITEM pMenuItem;
	UINT nID,nState,nIndex;
	CSize  size;
	CString strMenu;
	UINT nSize=GetMenuItemCount();	
	CDC	 *pDC =AfxGetMainWnd()->GetDC();

	for(nIndex=0;nIndex<nSize;nIndex++)
	{
		nID=GetMenuItemID(nIndex);					// get menu ID
		nState=GetMenuState(nIndex,MF_BYPOSITION);	// get menu state
		GetMenuString(nIndex,strMenu,MF_BYPOSITION);// get menu name
		pMenuItem=GetMenuItem(nIndex);	
		
		if((pMenuItem==NULL)||(pMenuItem->nID!=nID))
		{
			pMenuItem=new MENUITEM;			
			
			if(nID==0)
			{	
				// insert separator
				pMenuItem->strText = "";						// no name
				pMenuItem->nID = 0;								// separator's ID
				pMenuItem->itemSize=CSize(0,m_nSeparator);		// separator's default size
				pMenuItem->pImageList=NULL;						// separator has no image
				pMenuItem->pDisabledImageList=NULL;
				pMenuItem->pHotImageList=NULL;
				pMenuItem->nImageIndex=-1;
				pMenuItem->bIsSubMenu=FALSE;					// separator must not be popupmenu
				pMenuItem->pSubMenu=NULL;				
				
				// modify menu item to ownerdrawn style
				// if this menu is not a top-level menu
				CMenu::ModifyMenu(nIndex,MF_SEPARATOR|MF_BYPOSITION|MF_OWNERDRAW,0,(LPCTSTR)pMenuItem);
				
				// insert menu item to array
				m_MenuItemArr.InsertAt(nIndex,pMenuItem);					
			}
			else if(nID==-1)
			{
				// bypass popupmenu's item number	
				nState&=0x00FFL;	
				// insert popupmenu
				CMenuEx* pSubMenu=new CMenuEx;				
				// create new popupmenu
				pSubMenu->SetPopupMenu(TRUE);
				
				// load popupmenu from specific handle
				pSubMenu->LoadMenu((HMENU)(CMenu::GetSubMenu(nIndex)->Detach()));
				size=pDC->GetTextExtent(strMenu);
				
				pMenuItem->strText = strMenu;
				pMenuItem->nID = -1;					
				// specified menu item size,do not include image's size
				pMenuItem->itemSize.cx=size.cx+25;
				pMenuItem->itemSize.cy=2;				
				pMenuItem->pImageList=m_pImageList;		
				pMenuItem->pDisabledImageList=m_pDisabledImageList;
				pMenuItem->pHotImageList=m_pHotImageList;
				pMenuItem->nImageIndex=-1;
				pMenuItem->bIsSubMenu=TRUE;
				pMenuItem->pSubMenu=pSubMenu;		// popupmenu's pointor				
				
				CMenu::ModifyMenu(nIndex,nState|MF_POPUP|MF_BYPOSITION|MF_OWNERDRAW,(UINT)(pSubMenu->m_hMenu),(LPCTSTR)pMenuItem);
				
				m_MenuItemArr.InsertAt(nIndex,pMenuItem);
			}
			else
			{					
				// insert normal menu item
				size=pDC->GetTextExtent(strMenu);
				
				pMenuItem->strText = strMenu;
				pMenuItem->nID = nID;			
				pMenuItem->itemSize.cx=size.cx+10;
				pMenuItem->itemSize.cy=2;		
				pMenuItem->pImageList=m_pImageList;		
				pMenuItem->pDisabledImageList=m_pDisabledImageList;
				pMenuItem->pHotImageList=m_pHotImageList;
				pMenuItem->nImageIndex=-1;
				pMenuItem->bIsSubMenu=FALSE;
				pMenuItem->pSubMenu=NULL;
				
				CMenu::ModifyMenu(nIndex,nState|MF_BYPOSITION|MF_OWNERDRAW,nID,(LPCTSTR)pMenuItem);
				
				m_MenuItemArr.InsertAt(nIndex,pMenuItem);					
			}			
		}
		else if((nID!=-1)&&((pMenuItem->strText==strMenu)||!(nState & MF_OWNERDRAW)))
		{	
			// system don't auto insert popup menu item
		    pMenuItem->strText=strMenu;
			CMenu::ModifyMenu(nIndex,nState|MF_BYPOSITION|MF_OWNERDRAW,nID,(LPCTSTR)pMenuItem);
		}
	}
	
	for(nIndex=nSize;nIndex<GetMenuItemSize();nIndex++)
	{
		pMenuItem=m_MenuItemArr.GetAt(nIndex);
		m_MenuItemArr.RemoveAt(nIndex);
		delete pMenuItem;
	}	
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::InitPopupMenu(CMenu* pSubMenu,UINT nIndex,BOOL bSystem)
{
	//update pSubMenu's item to owerdrawn style
	if(bSystem)
		return;
	
	((CMenuEx*)pSubMenu)->UpdatePopupMenu();	
}
/////////////////////////////////////////////////////////////////////////////
void CMenuEx::MeasureItem(LPMEASUREITEMSTRUCT  lpMIS)
{
	// check measure ownerdraw menu or other controler
	if(lpMIS->CtlType!=ODT_MENU)		
		return;

	MENUITEM *lpMenuItem =(LPMENUITEM)lpMIS->itemData;
	
	// initialize width and height with itemSize
	lpMIS->itemWidth=lpMenuItem->itemSize.cx;
	lpMIS->itemHeight=lpMenuItem->itemSize.cy;

	// not separator,may be popupmenu or normal menu item
	if(lpMenuItem->nID!=0)
	{		
		IMAGEINFO info;

		if(lpMenuItem->pImageList!=NULL)
		{	
			// first add normal imagelist size
			lpMenuItem->pImageList->GetImageInfo(0,&info);				
			lpMIS->itemWidth+=(info.rcImage.right-info.rcImage.left);
			lpMIS->itemHeight+=(info.rcImage.bottom-info.rcImage.top);			
		}
		else if(lpMenuItem->pDisabledImageList!=NULL)
		{
			// or add disabled imagelist size
			lpMenuItem->pDisabledImageList->GetImageInfo(0,&info);				
			lpMIS->itemWidth+=(info.rcImage.right-info.rcImage.left);
			lpMIS->itemHeight+=(info.rcImage.bottom-info.rcImage.top);
		}
		else if(lpMenuItem->pHotImageList!=NULL)
		{
			// or add hot imagelist size
			lpMenuItem->pHotImageList->GetImageInfo(0,&info);				
			lpMIS->itemWidth+=(info.rcImage.right-info.rcImage.left);
			lpMIS->itemHeight+=(info.rcImage.bottom-info.rcImage.top);
		}
		else
		{		
			// add default size,if do not have imagelist
			lpMIS->itemWidth+=20;
			lpMIS->itemHeight+=20;
		}		
	}		
}
/////////////////////////////////////////////////////////////////////////////
UINT  CMenuEx::GetMenuItemSize() const 
{
	// get menu item counter
	return m_MenuItemArr.GetSize();
}
/////////////////////////////////////////////////////////////////////////////
LPMENUITEM CMenuEx::GetMenuItem(UINT nPosition)
{
	// get menu item by position
	if(nPosition>(UINT)m_MenuItemArr.GetUpperBound())
		return NULL;

	return m_MenuItemArr.GetAt(nPosition);
}
/////////////////////////////////////////////////////////////////////////////