⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcmenu.cpp

📁 深入剖析Visual C++编程技术及应用实例
💻 CPP
字号:
//*************************************************************************
// TCMenu.cpp : implementation file
//

#include "stdafx.h"			
#include "TCMenu.h"			

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


TCMenu::TCMenu()
{
	m_clrText =  GetSysColor (COLOR_MENUTEXT);
    m_clrBack = GetSysColor (COLOR_MENU);
    m_brBackground.CreateSolidBrush (m_clrBack);
    m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
    m_crText = m_clrText;
    m_bLBtnDown = FALSE;

    m_iconX = 16;		
    m_iconY = 16;		

    m_clrHilight = GetSysColor (COLOR_HIGHLIGHT);	
    m_brSelect.CreateSolidBrush (m_clrHilight);		
    m_clrHilightText = GetSysColor (COLOR_HIGHLIGHTTEXT);

    ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
    NONCLIENTMETRICS nm;
    nm.cbSize = sizeof (NONCLIENTMETRICS);


	VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,0,&nm,0)); 

    m_lf =  nm.lfMenuFont;
    m_iMenuHeight = nm.iMenuHeight;
    m_fontMenu.CreateFontIndirect (&m_lf);
}


TCMenu::~TCMenu()
{
	DestroyMenu();
}


BOOL TCMenu::DestroyMenu()
{

	int m;
	int numSubMenus = m_SubMenus.GetUpperBound();
	for(m = numSubMenus; m >= 0; m--)
		delete(m_SubMenus[m]);
	//分别删除子菜单
	m_SubMenus.RemoveAll();
	//删除全部
    if ((HBRUSH) m_brBackground != NULL)	
        m_brBackground.DeleteObject ();
    if ((HFONT)m_fontMenu !=NULL)			
        m_fontMenu.DeleteObject ();
    if ((HBRUSH)m_brSelect != NULL)
        m_brSelect.DeleteObject ();
	//删除其他的GDI对象

	int numItems = m_MenuList.GetUpperBound();
	for(m = 0; m <= numItems; m++)
			delete(m_MenuList[m]);
	//删除菜单项
	m_MenuList.RemoveAll();
	//删除全部的菜单项
	return(CMenu::DestroyMenu());
};


void TCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
    ASSERT(lpDIS != NULL);

    CDC* pDC = CDC::FromHandle(lpDIS->hDC);
    CRect rect;
    HICON hIcon;
    COLORREF crText = m_crText;
	//文本颜色  
	
	rect.CopyRect(&lpDIS->rcItem);
	//获取菜单项矩形
    
    UINT action = lpDIS->itemAction;
    UINT state = lpDIS->itemState;
    CString strText;
    LOGFONT lf;
    lf = m_lf;
	
    CFont dispFont;
    CFont *pFont;
        
    if (lpDIS->itemData != NULL)
    {
		UINT nIconNormal = (((TCMenuData*)(lpDIS->itemData))->menuIconNormal);
		UINT nIconSelected = (((TCMenuData*)(lpDIS->itemData))->menuIconSelected);
		UINT nIconDisabled = (((TCMenuData*)(lpDIS->itemData))->menuIconDisabled);
        strText = (((TCMenuData*) (lpDIS->itemData))->menuText);

        if(nIconNormal == -1)
			hIcon = NULL;
        else 
		{
			hIcon = NULL;
			//以下是根据不同的菜单状态,载入不同的图片资源
			if (state & ODS_SELECTED && !(state & ODS_GRAYED))		
			{
                if(nIconSelected != -1)
					hIcon = AfxGetApp ()->LoadIcon(nIconSelected);
			}
	        else
			{
				if(state & ODS_GRAYED)								
					if(nIconDisabled != -1)
						hIcon = AfxGetApp()->LoadIcon(nIconDisabled);
			};


			if(hIcon == NULL)
				hIcon = AfxGetApp()->LoadIcon(nIconNormal);
		}
    }
    else
    {
        strText.Empty();
        hIcon = NULL;
    }

    if ( (state & ODS_SELECTED) )
    {

        CPen *pOldPen = pDC->SelectObject (&m_penBack);
		//根据不同菜单状态,填充不同的色彩
        if (m_hilightStyle != Normal)
            pDC->FillRect (rect,&m_brBackground);
        else
            pDC->FillRect (rect,&m_brSelect);

        pDC->SelectObject (pOldPen);

		pDC->Draw3dRect (rect,GetSysColor (COLOR_3DHILIGHT),RGB(0,0,0));        

        if ((HFONT)dispFont != NULL)
                dispFont.DeleteObject ();
        dispFont.CreateFontIndirect (&lf);
        crText = m_clrHilightText;
    }
    else
    {
        CPen *pOldPen = pDC->SelectObject (&m_penBack);
        pDC->FillRect (rect,&m_brBackground);
        pDC->SelectObject (pOldPen);

        pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
        if ((HFONT)dispFont != NULL)
                dispFont.DeleteObject ();
        dispFont.CreateFontIndirect (&lf); //Normal

    }

   if (hIcon != NULL)
	{
	   //绘制图片
        DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hIcon,
					m_iconX,m_iconY,0,NULL,DI_NORMAL);
	};

    rect.left = rect.left +((m_iconX)?m_iconX:32) + 2; 

    if ( !strText.IsEmpty())
    {
        pFont->GetLogFont (&lf);

        int iOldMode = pDC->GetBkMode();

        pDC->SetBkMode( TRANSPARENT);
		UINT nFormat = DT_LEFT|DT_SINGLELINE|DT_EXPANDTABS|DT_VCENTER;
		if(!(lpDIS->itemState & ODS_GRAYED))
		{
			pDC->SetTextColor(crText);
	        pDC->DrawText (strText,rect,nFormat);
		}
		else
		{

			RECT offset = *rect;
			offset.left+=1;
			offset.right+=1;
			offset.top+=1;
			offset.bottom+=1;
			pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
			pDC->DrawText(strText,&offset, nFormat);


			pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
	        pDC->DrawText(strText,rect, nFormat);
		};
        pFont = pDC->SelectObject (&dispFont);
        pDC->SetBkMode( iOldMode );
        pDC->SelectObject (pFont); //set it to the old font
    }
    dispFont.DeleteObject ();
}


void TCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
	CWnd *pWnd = AfxGetMainWnd();					
    CDC *pDC = pWnd->GetDC();						
    CFont* pFont = pDC->SelectObject (&m_fontMenu);	
	LPCTSTR lpstrText = (((TCMenuData*)(lpMIS->itemData))->menuText);
	SIZE t;
	GetTextExtentPoint32(pDC->GetSafeHdc(), lpstrText, strlen(lpstrText), &t);
    pDC->SelectObject (pFont);						
    AfxGetApp()->m_pMainWnd->ReleaseDC (pDC);		

	lpMIS->itemWidth = m_iconX + t.cx + 10;
	lpMIS->itemHeight = m_iconY;
}

void TCMenu::SetIconSize (int width, int height)
{
    m_iconX = width;
    m_iconY = height;
}

void TCMenu::SetTextColor (COLORREF clrText)
{
    m_crText = clrText;
}

void TCMenu::SetBackColor (COLORREF clrBack)
{
    m_clrBack = clrBack;
    if ((HBRUSH)m_brBackground != NULL)
		m_brBackground.DeleteObject ();

    m_brBackground.CreateSolidBrush (clrBack);
}

void TCMenu::SetHighlightColor (COLORREF clrHilight)
{
    m_clrHilight = clrHilight;
    if ((HBRUSH)m_brSelect != NULL)
                    m_brSelect.DeleteObject ();

    m_brSelect.CreateSolidBrush (clrHilight);
}

void TCMenu::SetHighlightTextColor (COLORREF clrHilightText)
{
    m_clrHilightText = clrHilightText;
}


void TCMenu::SetHighlightStyle (HIGHLIGHTSTYLE hilightStyle)
{
    m_hilightStyle = hilightStyle;
}


BOOL TCMenu::AppendODMenu(LPCTSTR lpstrText,
						  UINT  nFlags,
						  UINT	nID,
						  UINT	nIconNormal,
						  UINT	nIconSelected,
						  UINT	nIconDisabled)
{
	if(!(nFlags & MF_OWNERDRAW))
		nFlags |= MF_OWNERDRAW;

	TCMenuData *mdata = new TCMenuData;
	m_MenuList.Add(mdata);
	//添加数据项
	lstrcpy(mdata->menuText, lpstrText);
	//复制菜单字符串
	//以下是设置菜单的图片类型
	mdata->menuIconNormal = nIconNormal;
	mdata->menuIconSelected = nIconSelected;
	mdata->menuIconDisabled = nIconDisabled;
	return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
};


BOOL TCMenu::ModifyODMenu(LPCTSTR lpstrText,
						  UINT	  nID,
						  UINT	  nIconNormal,
						  UINT	  nIconSelected,
						  UINT	  nIconDisabled)
{
	int numMenuItems = m_MenuList.GetUpperBound();
	TCMenuData *mdata;
	for(int m = 0; m <= numMenuItems; m++)
	{
		if((mdata = m_MenuList[m]) != NULL)
		{
			if(mdata->nID == nID)
			{
				delete(mdata);
				m_MenuList.RemoveAt(m);
				break;
			};
		};
	};
	//根据菜单项ID查找该数据项,然后进行删除
	mdata = new TCMenuData;
	m_MenuList.Add(mdata);
	lstrcpy(mdata->menuText, lpstrText);
	mdata->menuIconNormal = nIconNormal;
	mdata->menuIconSelected = nIconSelected;
	mdata->menuIconDisabled = nIconDisabled;
	//添加一个新的菜单项
	return(CMenu::ModifyMenu(nID, MF_BYCOMMAND | MF_OWNERDRAW, nID, (LPCTSTR)mdata));
};


BOOL TCMenu::LoadMenu(LPCTSTR lpszResourceName)
{
	return(TCMenu::LoadMenu(MAKEINTRESOURCE(lpszResourceName)));
};

BOOL TCMenu::LoadMenu(int nResource)
{

	DWORD dwSize;
	WORD wrd = MAKEWORD(nResource, 0);
	HRSRC hRsrc = FindResource(NULL, (LPCTSTR)wrd, RT_MENU);
	if(hRsrc == NULL)
	{
		TRACE0("TCMenu::LoadMenu() - Failed to find Menu Resource\n");
		ASSERT(FALSE);
	};

	dwSize = SizeofResource(NULL, hRsrc);


	HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
	if(hGlobal == NULL)
	{
		TRACE0("TCMenu::LoadMenu() - Failed to load Menu Resource\n");
		ASSERT(FALSE);
	};

	if(!CMenu::CreateMenu())
	{
		TRACE0("TCMenu::LoadMenu() - Failed to create Menu\n");
		ASSERT(FALSE);
	};

	MENUITEMTEMPLATEHEADER*	pTpHdr = (MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
	BYTE*					pTp   = (BYTE*)pTpHdr + 
									(sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);


	TCMenuData*	pData = NULL;			
	WORD		dwFlags = 0;			
	WORD		dwID	= 0;			
	BOOL		bLastPopup = 0;			
	UINT		uFlags;					
	char		caption[80];			
	int			nLen   = 0;				
	CTypedPtrArray<CPtrArray, TCMenu*>	m_Stack;	
	m_Stack.Add(this);								

	do
	{

		memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);
		if(!(dwFlags & MF_POPUP))
		{
			memcpy(&dwID, pTp, sizeof(WORD));				
			pTp+=sizeof(WORD);
		}
		else
			dwID = 0;

		uFlags = (UINT)dwFlags;		
		if(uFlags & MF_END)			
			uFlags -= MF_END;

		nLen = 0;
		char *ch = (char*)pTp;
		while(*ch != 0)
		{
			caption[nLen] = ch[0];
			nLen++;			
			ch+=2;			
		};
		caption[nLen] = 0;	
		pTp+=((nLen+1)*2);	


		if(dwFlags & MF_POPUP)
		{
			if(dwFlags & MF_END)
				bLastPopup = TRUE;

			TCMenu* pSubMenu = new TCMenu;
			pSubMenu->CreatePopupMenu();

			m_Stack[m_Stack.GetUpperBound()]->AppendMenu(uFlags, (UINT)pSubMenu->m_hMenu, caption);
			m_Stack.Add(pSubMenu);				
			m_SubMenus.Add(pSubMenu);			
		}
		else
		{
			m_Stack[m_Stack.GetUpperBound()]->AppendODMenu(caption, uFlags, dwID, -1, -1, -1);
			if(dwFlags & MF_END)
				m_Stack.RemoveAt(m_Stack.GetUpperBound());

			if(bLastPopup)
			{
				bLastPopup = FALSE;
				m_Stack.RemoveAt(m_Stack.GetUpperBound());
			};
		};


	}while(m_Stack.GetUpperBound() != -1);
	
	return(TRUE);
};

⌨️ 快捷键说明

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