menuex.cpp

来自「深入浅出Visual C++入门进阶与应用实例 随书光盘 作者 何志丹」· C++ 代码 · 共 254 行

CPP
254
字号
// MenuEx.cpp: implementation of the CMenuEx class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Ex030204.h"
#include "MenuEx.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMenuEx::CMenuEx()
{

}

CMenuEx::~CMenuEx()
{

}

void CMenuEx::InitMenu(CMenu* pMenu )
{
	CMenu *pSubMenu;
	UINT nCount,nSubCount,nID;
	nCount=pMenu->GetMenuItemCount();//子菜单的列数
	for(UINT i=0;i<nCount;i++)             
	{
		pSubMenu =pMenu->GetSubMenu(i);
		if(NULL == pSubMenu)
		{//出错忽略此列
			ASSERT(false);
			continue ;
		}
		nSubCount=pSubMenu->GetMenuItemCount();//此列菜单菜单项的个数
		for(UINT j=0;j<nSubCount;j++)
		{
			nID=pSubMenu->GetMenuItemID(j);			
			//将框架菜单所有菜单都添加MF_OWNERDRAW标志
			pSubMenu->ModifyMenu(j,MF_BYPOSITION|MF_OWNERDRAW,nID); 
		}	
	}	
}

void CMenuEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
	if(ODT_MENU != lpMeasureItemStruct->CtlType )
		return ;

	if(ID_SEPARATOR != lpMeasureItemStruct->itemID)     //设定非分隔线的大小	
	{
		lpMeasureItemStruct->itemHeight = 18;    
		lpMeasureItemStruct->itemWidth = 138;	
	}	
	else//设定分隔线的大小	
	{		
		lpMeasureItemStruct->itemHeight = 1;     		
		lpMeasureItemStruct->itemWidth = 138;	
	}
}

void CMenuEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct )
{
	if(ODT_MENU != lpDrawItemStruct->CtlType)
		return ;

	LPDRAWITEMSTRUCT& lpDraw=lpDrawItemStruct;  //起个别名,好用一点
	LPMENUITEM lpItem;
	lpItem =(LPMENUITEM)lpDrawItemStruct->itemData;
	
	//得到菜单的设备指针,用来绘制菜单
	CDC* pDC=CDC::FromHandle(lpDraw->hDC);  	
	CBrush brushBK(RGB(255,255,255)) ;
	pDC->FillRect(&lpDraw->rcItem,&brushBK);//填充背景,"白纸"
	pDC->SetBkMode(TRANSPARENT);//透明的,有文字和没文字的地方背景一样
	pDC->SetTextColor(RGB(0,0,0));//文字的颜色,"黑字"
	pDC->TextOut(lpDraw->rcItem.left+30,lpDraw->rcItem.top+5,lpItem->strText);  //输出菜单标题
}

BOOL CMenuEx::LoadMenu(UINT uMenu)
{
	//重新读入菜单,创建为popup菜单,才能自画(由框架调用MesureItem() 和 DrawItem()
	HMENU hMenu = ::CreateMenu();
	this->Attach(hMenu);

	CMenu Menu;		//临时菜单
	UINT uID;
	Menu.LoadMenu(uMenu);
	for(int i = 0; i < (int)Menu.GetMenuItemCount(); i++)
	{
		uID = Menu.GetMenuItemID(i);
		if(uID == 0)			//分隔符
		{
			::AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
		}
		else if((int)uID == -1)		//弹出菜单(即子菜单)
		{
			CMenu *pSubMenu = Menu.GetSubMenu(i);
			
			//创建子菜单	
			HMENU hSubMenu = ::CreatePopupMenu();
			CString strPopup;
			Menu.GetMenuString(i,strPopup,MF_BYPOSITION);
			::InsertMenu(hMenu,i,MF_BYPOSITION | MF_POPUP | MF_STRING,(UINT)hSubMenu,strPopup);						
			
			//对子菜单递归调用ChangeMenuStyle(),把子菜单改为MF_OWNERDRAW风格
			ChangeMenuStyle(pSubMenu,hSubMenu);
		}
		else					//正常的菜单项
		{
			CString strText;
			Menu.GetMenuString(uID,strText,MF_BYCOMMAND);
			AppendMenu(MF_STRING,uID,strText);
		}
	}
	Menu.DestroyMenu();			//销毁临时菜单
	return TRUE;
}

void CMenuEx::ChangeMenuStyle(CMenu *pMenu,HMENU hNewMenu)
{
	CMenuEx *pNewMenu;
	pNewMenu = new CMenuEx;
	pNewMenu->Attach(hNewMenu);
	m_SubMenuArr.Add(pNewMenu);


	UINT uID;
	int nItemCount = pMenu->GetMenuItemCount();
	for(int i = 0; i < nItemCount; i++)
	{
		uID = pMenu->GetMenuItemID(i);
		if(uID == 0)			//分隔符
		{
			::AppendMenu(hNewMenu,MF_SEPARATOR,0,NULL);
			CString strText;
			MENUITEM *pMenuItem = new MENUITEM;
			pMenuItem->uID = 0;
			m_MenuItemArr.Add(pMenuItem);			
			::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem);
		}
		else if(uID == -1)		//弹出菜单(即子菜单)
		{
			CMenu *pSubMenu = pMenu->GetSubMenu(i);
			HMENU hPopMenu = ::CreatePopupMenu();
			CString strPopup;
			pMenu->GetMenuString(i,strPopup,MF_BYPOSITION);
			::InsertMenu(hNewMenu,i,MF_BYPOSITION | MF_POPUP,(UINT)hPopMenu,strPopup);
			MENUITEM *pMenuItem = new MENUITEM;
			pMenuItem->uID = -1;
			pMenuItem->strText = strPopup;
			m_MenuItemArr.Add(pMenuItem);
			::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem);			
			ChangeMenuStyle(pSubMenu,hPopMenu);			
		}
		else					//正常的菜单项
		{
			CString strText;
			pMenu->GetMenuString(uID,strText,MF_BYCOMMAND);
			MENUITEM *pMenuItem = new MENUITEM;
			pMenuItem->uID = pMenu->GetMenuItemID(i);
			pMenu->GetMenuString(pMenuItem->uID,pMenuItem->strText,MF_BYCOMMAND);
			m_MenuItemArr.Add(pMenuItem);
			UINT uState = pMenu->GetMenuState(i,MF_BYPOSITION);
			::AppendMenu(hNewMenu,MF_OWNERDRAW | MF_BYCOMMAND | uState,uID,(LPCTSTR)pMenuItem);
		}
	}
}

BOOL CMenuEx::AppendMenuEx(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem)
{
	MENUITEM *pMenuItem = new MENUITEM;
	pMenuItem->strText = lpszNewItem;
	pMenuItem->uID = nIDNewItem;
	nFlags &= ~MF_STRING;
	nFlags |= MF_OWNERDRAW;
	m_MenuItemArr.Add(pMenuItem);
	return CMenu::AppendMenu(nFlags,nIDNewItem,(LPCTSTR)pMenuItem);
}

BOOL CMenuEx::ModifyMenuEx(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem)
{
	UINT uItemID = 0;
	if(nFlags & MF_BYPOSITION)
	{
		uItemID = GetMenuItemID((int)nPosition);
	}
	else
	{
		uItemID = nPosition;
	}
	//普通菜单项和弹出式菜单
	MENUITEM *pMenuItem = NULL;
	for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
	{
		pMenuItem = m_MenuItemArr.GetAt(i);
		if(pMenuItem->uID == uItemID)
		{
			pMenuItem->strText = lpszNewItem;
			if((int)nIDNewItem != 0)
				pMenuItem->uID = nIDNewItem;
			break;
		}
	}
	//没找到对应的菜单项
	if(i >= m_MenuItemArr.GetSize())
	{
		MENUITEM *pMenuItem = new MENUITEM;
		pMenuItem->strText = lpszNewItem;
		pMenuItem->uID = nIDNewItem;
		m_MenuItemArr.Add(pMenuItem);
	}
	nFlags &= ~MF_STRING;
	nFlags |= MF_OWNERDRAW;
	
	return CMenu::ModifyMenu(nPosition,nFlags,nIDNewItem,(LPCTSTR)pMenuItem);
}

BOOL CMenuEx::RemoveMenuEx(UINT nPosition, UINT nFlags)
{
	UINT uItemID = 0;
	if(nFlags & MF_BYPOSITION)
	{
		uItemID = GetMenuItemID((int)nPosition);
	}
	else
	{
		uItemID = nPosition;
	}
	if((int) uItemID >= 0)			//普通菜单项或分割条
	{
		for(int i = 0; i < m_MenuItemArr.GetSize(); i++)
		{
			MENUITEM *pMenuItem = m_MenuItemArr.GetAt(i);
			if(pMenuItem->uID == uItemID)
			{
				m_MenuItemArr.RemoveAt(i);
				break;
			}
		}
	}
	else							//子菜单
	{
	}
	return CMenu::RemoveMenu(nPosition,nFlags);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?