📄 bcmenu.cpp
字号:
//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.//// This program is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//#####DESCRIPTIONBEGIN#### ////*************************************************************************// BCMenu.cpp : implementation file// Version : 2.63// Date : December 2, 1999// Author : Brent Corkum// Email : corkum@rocscience.com// Latest Version : http://www.rocscience.com/~corkum/BCMenu.html// // Bug Fixes and portions of code supplied by://// Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,// Robert Edward Caldecott,Kenny Goers,Leonardo Zide,// Stefan Kuhr,Reiner Jung,Martin Vladic,Kim Yoo Chul,// Oz Solomonovich//// You are free to use/modify this code but leave this header intact.// This class is public domain so you are free to use it any of// your applications (Freeware,Shareware,Commercial). All I ask is// that you let me know so that if you have a real winner I can// brag to my buddies that some of my code is in your app. I also// wouldn't mind if you sent me a copy of your application since I// like to play with new stuff.//*************************************************************************//####DESCRIPTIONEND####//==========================================================================#include "stdafx.h" // Standard windows header file#include "BCMenu.h" // BCMenu class declaration#include <afxpriv.h> //SK: makes A2W and other spiffy AFX macros work#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define GAP 1#ifndef OBM_CHECK#define OBM_CHECK 32760 // from winuser.h#endif#if _MFC_VER <0x400#error This code does not work on Versions of MFC prior to 4.0#endifstatic CPINFO CPInfo;enum Win32Type{Win32s,Windoze95,WinNT3,WinNT4orHigher};Win32Type IsShellType(){ Win32Type ShellType; DWORD winVer; OSVERSIONINFO *osvi; winVer=GetVersion(); if(winVer<0x80000000){/*NT */ ShellType=WinNT3; osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO)); if (osvi!=NULL){ memset(osvi,0,sizeof(OSVERSIONINFO)); osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO); GetVersionEx(osvi); if (osvi->dwMajorVersion>=4L) ShellType=WinNT4orHigher;//yup, it is NT 4 or higher! free(osvi); } } else if (LOBYTE(LOWORD(winVer))<4) ShellType=Win32s;/*Win32s*/ else ShellType=Windoze95;/*Windoze95*/ return ShellType;}static Win32Type g_Shell=IsShellType();void BCMenuData::SetAnsiString(LPCSTR szAnsiString){USES_CONVERSION;SetWideString(A2W(szAnsiString)); //SK: see MFC Tech Note 059}CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE//depending on the MFC-Version we are using{CString strText;if (m_szMenuText) {#ifdef UNICODE strText = m_szMenuText;#elseUSES_CONVERSION; strText=W2A(m_szMenuText); //SK: see MFC Tech Note 059#endif }return strText;}CTypedPtrArray<CPtrArray, HMENU> BCMenu::m_AllSubMenus; // Stores list of all sub-menus/* =============================================================================== BCMenu::BCMenu() TCMeny::~BCMenu() ----------------- Constructor and Destructor. ===============================================================================*/BCMenu::BCMenu(){ m_bDynIcons = FALSE; // O.S. - no dynamic icons by default disable_old_style=FALSE; m_iconX = 16; // Icon sizes default to 16 x 16 m_iconY = 15; // ... m_selectcheck = -1; m_unselectcheck = -1; checkmaps=NULL; checkmapsshare=FALSE; // set the color used for the transparent background in all bitmaps m_bitmapBackground=RGB(192,192,192); //gray m_bitmapBackgroundFlag=FALSE; GetCPInfo(CP_ACP,&CPInfo);}BCMenu::~BCMenu(){ DestroyMenu();}BOOL BCMenu::IsNewShell (){return (Windoze95==g_Shell || WinNT4orHigher==g_Shell);}BCMenuData::~BCMenuData(){ if(bitmap) delete(bitmap); delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"}void BCMenuData::SetWideString(const wchar_t *szWideString){delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"if (szWideString) { m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)]; if (m_szMenuText) wcscpy(m_szMenuText,szWideString); }else m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs}BOOL BCMenu::IsMenu(CMenu *submenu){ int m; int numSubMenus = m_AllSubMenus.GetUpperBound(); for(m=0;m<=numSubMenus;++m){ if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE); } return(FALSE);}BOOL BCMenu::IsMenu(HMENU submenu){ int m; int numSubMenus = m_AllSubMenus.GetUpperBound(); for(m=0;m<=numSubMenus;++m){ if(submenu==m_AllSubMenus[m])return(TRUE); } return(FALSE);}BOOL BCMenu::DestroyMenu(){ // Destroy Sub menus: int m,n; int numAllSubMenus = m_AllSubMenus.GetUpperBound(); for(n = numAllSubMenus; n>= 0; n--){ if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n); } int numSubMenus = m_SubMenus.GetUpperBound(); for(m = numSubMenus; m >= 0; m--){ numAllSubMenus = m_AllSubMenus.GetUpperBound(); for(n = numAllSubMenus; n>= 0; n--){ if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n); } delete((BCMenu *)FromHandle(m_SubMenus[m])); } m_SubMenus.RemoveAll(); // Destroy menu data int numItems = m_MenuList.GetUpperBound(); for(m = 0; m <= numItems; m++)delete(m_MenuList[m]); m_MenuList.RemoveAll(); if(checkmaps&&!checkmapsshare){ delete checkmaps; checkmaps=NULL; } // Call base-class implementation last: return(CMenu::DestroyMenu());};/////////////////////////////////////////////////////////////////////////////// BCMenu message handlers/*==========================================================================void BCMenu::DrawItem(LPDRAWITEMSTRUCT)---------------------------------------Called by the framework when a particular item needs to be drawn. Weoveride this to draw the menu item in a custom-fashion, including iconsand the 3D rectangle bar.==========================================================================*/void BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS){ ASSERT(lpDIS != NULL); CDC* pDC = CDC::FromHandle(lpDIS->hDC); CRect rect; UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags); if(state & MF_SEPARATOR){ rect.CopyRect(&lpDIS->rcItem); rect.top+=rect.Height()>>1; pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP); } else{ CRect rect2; BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE; BOOL checkflag=FALSE; COLORREF crText = GetSysColor(COLOR_MENUTEXT); COLORREF m_clrBack=GetSysColor(COLOR_MENU); CBrush m_brBackground,m_brSelect; CPen m_penBack; int x0,y0,dy; int nIconNormal=-1,xoffset=-1; CImageList *bitmap=NULL; CFont m_fontMenu; LOGFONT m_lf; // set some colors and the font m_penBack.CreatePen (PS_SOLID,0,GetSysColor(COLOR_MENU)); m_brBackground.CreateSolidBrush(GetSysColor(COLOR_MENU)); m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT)); NONCLIENTMETRICS nm; nm.cbSize = sizeof (NONCLIENTMETRICS); VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); m_lf = nm.lfMenuFont; m_fontMenu.CreateFontIndirect (&m_lf); // draw the colored rectangle portion rect.CopyRect(&lpDIS->rcItem); rect2=rect; // draw the up/down/focused/disabled state UINT state = lpDIS->itemState; CString strText; LOGFONT lf; lf = m_lf; CFont dispFont; CFont *pFont=NULL; if(lpDIS->itemData != NULL){ nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal); xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset); bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap); strText = ((BCMenuData*) (lpDIS->itemData))->GetString(); if(state&ODS_CHECKED && nIconNormal<0){ if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE; else if(m_unselectcheck>0) checkflag=TRUE; } else if(nIconNormal != -1){ standardflag=TRUE; if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE; else if(state&ODS_GRAYED) disableflag=TRUE; } } else{ strText.Empty(); } if(state&ODS_SELECTED){ // draw the down edges CPen *pOldPen = pDC->SelectObject (&m_penBack); // You need only Text highlight and thats what you get if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED) rect2.SetRect(rect.left+m_iconX+4+GAP,rect.top,rect.right,rect.bottom); pDC->FillRect (rect2,&m_brSelect); pDC->SelectObject (pOldPen); if((HFONT)dispFont != NULL)dispFont.DeleteObject (); dispFont.CreateFontIndirect (&lf); crText = GetSysColor(COLOR_HIGHLIGHTTEXT); } else { CPen *pOldPen = pDC->SelectObject (&m_penBack); pDC->FillRect (rect,&m_brBackground); pDC->SelectObject (pOldPen); // draw the up edges pDC->Draw3dRect (rect,m_clrBack,m_clrBack); if ((HFONT)dispFont != NULL) dispFont.DeleteObject (); dispFont.CreateFontIndirect (&lf); //Normal } // draw the text if there is any //We have to paint the text only if the image is nonexistant dy = (rect.Height()-4-m_iconY)/2; dy = dy<0 ? 0 : dy; if(checkflag||standardflag||selectedflag||disableflag){ rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3, rect.top+m_iconY+3+dy); pDC->Draw3dRect (rect2,m_clrBack,m_clrBack); if(checkflag && checkmaps){ pDC->FillRect (rect2,&m_brBackground); rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4, rect.top+m_iconY+4+dy); pDC->Draw3dRect (rect2,m_clrBack,m_clrBack); CPoint ptImage(rect.left+2,rect.top+2+dy); if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT); else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT); } else if(disableflag){ if(!selectedflag){ CBitmap bitmapstandard; GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard); rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4, rect.top+m_iconY+4+dy); pDC->Draw3dRect (rect2,m_clrBack,m_clrBack); if(disable_old_style) DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY, (HBITMAP)(bitmapstandard),0,0); else DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY, bitmapstandard,0,0); bitmapstandard.DeleteObject(); } } else if(selectedflag){ pDC->FillRect (rect2,&m_brBackground); rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4, rect.top+m_iconY+4+dy); if (IsNewShell()){ if(state&ODS_CHECKED) pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT)); else pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW)); } CPoint ptImage(rect.left+2,rect.top+2+dy); if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT); } else{ if(state&ODS_CHECKED){ CBrush brush; COLORREF col =GetSysColor(COLOR_3DLIGHT); brush.CreateSolidBrush(col); pDC->FillRect(rect2,&brush); brush.DeleteObject(); rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4, rect.top+m_iconY+4+dy); if (IsNewShell()) pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT)); } else{ pDC->FillRect (rect2,&m_brBackground); rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4, rect.top+m_iconY+4+dy); pDC->Draw3dRect (rect2,m_clrBack,m_clrBack); } CPoint ptImage(rect.left+2,rect.top+2+dy); if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT); } } if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){ rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1, rect.top+m_iconY+2+dy); CMenuItemInfo info; info.fMask = MIIM_CHECKMARKS; ::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID, MF_BYCOMMAND, &info); if(state&ODS_CHECKED || info.hbmpUnchecked) { Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED, state&ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked); } } //This is needed always so that we can have the space for check marks x0=rect.left;y0=rect.top; rect.left = rect.left + m_iconX + 8 + GAP; if(!strText.IsEmpty()){ CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1); // Find tabs CString leftStr,rightStr; leftStr.Empty();rightStr.Empty(); int tablocr=strText.ReverseFind(_T('\t')); if(tablocr!=-1){ rightStr=strText.Mid(tablocr+1); leftStr=strText.Left(strText.Find(_T('\t'))); rectt.right-=m_iconX; } else leftStr=strText; int iOldMode = pDC->GetBkMode(); pDC->SetBkMode( TRANSPARENT); // Draw the text in the correct colour: UINT nFormat = DT_LEFT|DT_SINGLELINE|DT_VCENTER; UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER; if(!(lpDIS->itemState & ODS_GRAYED)){ pDC->SetTextColor(crText); pDC->DrawText (leftStr,rectt,nFormat); if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr); } else{ // Draw the disabled text if(!(state & ODS_SELECTED)){ RECT offset = *rectt; offset.left+=1; offset.right+=1; offset.top+=1; offset.bottom+=1; pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT)); pDC->DrawText(leftStr,&offset, nFormat);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -