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

📄 bcmenu.cpp

📁 很简单的小程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//*************************************************************************
// BCMenu.cpp : implementation file
// Version : 2.1
// Date : April 2, 1998
// Author : Brent Corkum
// 
// Portions of code supplied by:
// Ben Ashley,Girish Bharadwaj,Jean-Edouard Lachand-Robert,
// Robert Edward Caldecott,Kenny Goers,Leonardo Zide,
// Stefan Kuhr
//
// Bug Fixes:
// Stefan Kuhr,Martin Vladic
//
// You are free to use/modify this code but leave this header intact.
//

#include "stdafx.h"        // Standard windows header file
#include "BCMenu.h"        // BCMenu class declaration

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static 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
#endif

static CPINFO CPInfo;

enum Win32Type{
Win32s,
Windoze95,
WinNT3,
WinNT4orHigher
};


Win32Type IsNewShell()
{
  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=IsNewShell();

void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
{
  ASSERT(szAnsiString);
  int iBufSize=(CPInfo.MaxCharSize==1)?strlen(szAnsiString):_mbstrlen(szAnsiString);
  iBufSize++;//Increment for the terminating NULL 
  wchar_t *szText=new wchar_t[iBufSize];

  VERIFY(MultiByteToWideChar(
    CP_ACP,     // code page 
    MB_PRECOMPOSED,     // character-type options 
    szAnsiString,       // address of string to map 
    -1, // number of characters in string 
    szText,     // address of wide-character buffer 
    iBufSize*sizeof(wchar_t)// size of buffer 
   ));
  ASSERT(wcslen(szText)==strlen(szAnsiString));
  wcscpy(menuText,szText);
  delete[] szText;
}

CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
//depending on the MFC-Version we are using
{
  CString strText;

#ifdef UNICODE
  strText = menuText;
#else
  int iLen=(wcslen(menuText)+1)*sizeof(wchar_t);
  char *szAnsiString=new char[iLen];
    
  if (*menuText){
    VERIFY(WideCharToMultiByte(
            CP_ACP,     // code page 
            0,  // performance and mapping flags 
            menuText,   // address of wide-character string 
            -1, // number of characters in string 
            szAnsiString,       // address of buffer for new string 
            iLen,       // size of buffer 
            NULL,       // address of default for unmappable characters  
            NULL        // address of flag set when default char. used 
            ));
    strText=szAnsiString;
  }
  else strText.Empty();
  delete[] szAnsiString;
#endif    
return strText;
}


/*
 
===============================================================================
  BCMenu::BCMenu()
  TCMeny::~BCMenu()
  -----------------

  Constructor and Destructor.
 
===============================================================================
*/

BCMenu::BCMenu()
{
  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();
}

BCMenuData::~BCMenuData()
{
  if(bitmap)delete(bitmap);
}

BOOL BCMenu::IsMenu(CMenu *submenu)
{
  int m;

  int numSubMenus = m_SubMenus.GetUpperBound();
  for(m=0;m<=numSubMenus;++m){
    if(submenu==m_SubMenus[m])return(TRUE);
  }
  return(FALSE);
}

BOOL BCMenu::DestroyMenu()
{
  // Destroy Sub menus:
  int m;
  int numSubMenus = m_SubMenus.GetUpperBound();
  for(m = numSubMenus; m >= 0; m--)delete(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.  We
overide this to draw the menu item in a custom-fashion, including icons
and 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;
    CBitmap bitmapstandard;
    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 action = lpDIS->itemAction;
    UINT state = lpDIS->itemState;
    CString strText;
    LOGFONT lf;
    lf = m_lf;

    CFont dispFont;
    CFont *pFont;
      
    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){
          HBITMAP hbmp=LoadSysColorBitmap(nIconNormal);
          if(hbmp){
            bitmapstandard.Attach(hbmp);
            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),xoffset*m_iconX,0);
            else
              DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
                         bitmapstandard,xoffset*m_iconX,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 (Windoze95==g_Shell || WinNT4orHigher==g_Shell){
          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 (Windoze95==g_Shell || WinNT4orHigher==g_Shell)
            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);
          if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
          pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
          pDC->DrawText(leftStr,rectt, nFormat);
          if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
        }
        else{
        // And the standard Grey text:
          pDC->SetTextColor(m_clrBack);
          pDC->DrawText(leftStr,rectt, nFormat);
          if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
        }
      }
      pFont = pDC->SelectObject (&dispFont);
      pDC->SetBkMode( iOldMode );
      pDC->SelectObject (pFont); //set it to the old font
    }

    m_penBack.DeleteObject();
    m_brBackground.DeleteObject();
    m_fontMenu.DeleteObject();
    m_brSelect.DeleteObject();
    dispFont.DeleteObject ();
  }
}


/*
==========================================================================
void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
---------------------------------------------

Called by the framework when it wants to know what the width and height
of our item will be.  To accomplish this we provide the width of the
icon plus the width of the menu text, and then the height of the icon.
 
==========================================================================
*/

void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
  UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
  if(state & MF_SEPARATOR){
    lpMIS->itemWidth = 0;
    lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
  }
  else{
    CFont m_fontMenu;
    LOGFONT m_lf;
    ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
    NONCLIENTMETRICS nm;
    nm.cbSize = sizeof (NONCLIENTMETRICS);
    VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
           nm.cbSize,&nm,0)); 

⌨️ 快捷键说明

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