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

📄 menuex.cpp

📁 Visual C++开发使用编程200例——Windows界面编程
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		if(grayedflag && !m_bDrawOnlyGray)
          Draw3DCheckmark2(pDC, rect2, state&ODS_SELECTED,&m_brLightBackground,
                        state&ODS_CHECKED ? info.hbmpChecked :
                        info.hbmpUnchecked);
		else
          Draw3DCheckmark2(pDC, rect2, state&ODS_SELECTED,&m_brBackground,
                        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 ();
  }
  m_brLightBackground.DeleteObject();
}


/*
==========================================================================
void CMenuEx::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 CMenuEx::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
  UINT state = (((CMenuExData*)(lpMIS->itemData))->nFlags);
  UINT grayed= (((CMenuExData*)(lpMIS->itemData))->nFlagsEx) & MF_DRAWGRAYED;
  UINT larrow= (((CMenuExData*)(lpMIS->itemData))->nFlagsEx) & MF_LASTARROW;
  /*if ((!m_bEnableArrows) && (state & MF_POPUP))
  {
	  CMenuEx* pMenu=this;
	  int t=FindMenuPos((CMenuExData*) (lpMIS->itemData),pMenu);
	  if (t>=0)grayed=CheckIfGrayed(pMenu->GetSubMenu(t));
  }*/
  if (larrow)
  {
	  if(m_bDrawGrayed || !m_bShowLastArrow)
	  {
		lpMIS->itemWidth = 0;
		lpMIS->itemHeight = 0;
		return;
	  }
  }
#ifdef ASK_APP_DRAW
  CWinAppEx* app=(CWinAppEx*)AfxGetApp();
  ASSERT(app->IsKindOf(RUNTIME_CLASS(CWinAppEx)));
  if (grayed && !app->CheckForGrayedMenuPaint())
#else
  if (grayed && !m_bDrawGrayed) 
#endif
  {
    lpMIS->itemWidth = 0;
    lpMIS->itemHeight = 0;
	return;
  }
  if(state & MF_SEPARATOR && !((((CMenuExData*)(lpMIS->itemData))->nFlagsEx) & MF_LASTARROW))
  {
    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)); 
    m_lf =  nm.lfMenuFont;
    m_fontMenu.CreateFontIndirect (&m_lf);

    // Obtain the width of the text:
    CWnd *pWnd = AfxGetMainWnd();            // Get main window
    CDC *pDC = pWnd->GetDC();              // Get device context
    CFont* pFont;    // Select menu font in...
    
    if (IsNewShell())
        pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
        
    //Get pointer to text SK
    const wchar_t *lpstrText = ((CMenuExData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
    
        
    SIZE size;

    if (Win32s!=g_Shell)
      VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
             wcslen(lpstrText),&size)); //SK should also work on 95
#ifndef UNICODE //can't be UNICODE for Win32s
    else{//it's Win32suckx
      RECT rect;
      rect.left=rect.top=0;
      size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
                       wcslen(lpstrText),&rect,
                       DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
      //+3 makes at least three pixels space to the menu border
      size.cx=rect.right-rect.left+3;
      size.cx += 3*(size.cx/wcslen(lpstrText));
    }
#endif    

    CSize t = CSize(size);
    if(IsNewShell())
      pDC->SelectObject (pFont);  // Select old font in
    AfxGetMainWnd()->ReleaseDC(pDC);  // Release the DC

    // Set width and height:

    lpMIS->itemWidth = m_iconX + t.cx + m_iconX + GAP;
    int temp = GetSystemMetrics(SM_CYMENU);
    lpMIS->itemHeight = temp>m_iconY+4 ? temp : m_iconY+4;
    m_fontMenu.DeleteObject();
  }
}

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

BOOL CMenuEx::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal,int nFlagsEx)
{
	CHAR chr='\0';
	if (!lpstrText)lpstrText=&chr;
	USES_CONVERSION;
	return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal,nFlagsEx);//SK: See MFC Tech Note 059
}


BOOL CMenuEx::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
                           int nIconNormal,int nFlagsEx)
{
  // Add the MF_OWNERDRAW flag if not specified:
  WCHAR chr='\0';
  if (!lpstrText)lpstrText=&chr;
  if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW;
  
  nFlags |= MF_OWNERDRAW;

  CMenuExData *mdata = new CMenuExData;
  m_MenuList.Add(mdata);
  mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
  
  mdata->menuIconNormal = nIconNormal;
  mdata->xoffset=-1;
  if(nIconNormal>=0){
    mdata->xoffset=0;
    LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
    if(mdata->bitmap)mdata->bitmap->DeleteImageList();
    else mdata->bitmap=new(CImageList);
    mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
    AddBitmapToImageList(mdata->bitmap,nIconNormal);
  }
  mdata->nFlags = nFlags;
  mdata->nFlagsEx=nFlagsEx;
  mdata->nID = nID;
  return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
}


BOOL CMenuEx::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal, int nFlagsEx)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal,nFlagsEx);//SK: see MFC Tech Note 059
}

BOOL CMenuEx::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal, int nFlagsEx)
{
  int nLoc;
  CMenuExData *mdata;

  // Find the old CMenuExData structure:
  CMenuEx *psubmenu = FindMenuOption(nID,nLoc);
  if(psubmenu && nLoc>=0)
	  mdata = psubmenu->m_MenuList[nLoc];
  else{
  // Create a new CMenuExData structure:
    mdata = new CMenuExData;
    m_MenuList.Add(mdata);
  }
  ASSERT(mdata);
  if(lpstrText)
     mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
  mdata->menuIconNormal = nIconNormal;
  mdata->xoffset=-1;
  if(nIconNormal>=0){
    mdata->xoffset=0;
    LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
    if(mdata->bitmap)mdata->bitmap->DeleteImageList();
    else mdata->bitmap=new(CImageList);
    mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
    AddBitmapToImageList(mdata->bitmap,nIconNormal);
  }
  mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
  mdata->nID = nID;
  if(nFlagsEx>=0) mdata->nFlagsEx=nFlagsEx;
  return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}


BOOL CMenuEx::ModifyODMenuA(const char *lpstrText,const char *OptionText,
                           int nIconNormal, int nFlagsEx)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal,nFlagsEx);//SK: see MFC  Tech Note 059
}


BOOL CMenuEx::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
                           int nIconNormal, int nFlagsEx)
{
  CMenuExData *mdata;

  // Find the old CMenuExData structure:
  mdata=FindMenuOption(OptionText);
  if(mdata){
    if(nFlagsEx>=0) mdata->nFlagsEx=nFlagsEx;
    if(lpstrText)
        mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
    mdata->menuIconNormal = nIconNormal;
    mdata->xoffset=-1;
    if(nIconNormal>=0){
      mdata->xoffset=0;
      if(mdata->bitmap)mdata->bitmap->DeleteImageList();
      else mdata->bitmap=new(CImageList);
      mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
      AddBitmapToImageList(mdata->bitmap,nIconNormal);
    }
    return(TRUE);
  }
  return(FALSE);
}

CMenuExData *CMenuEx::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
{
  CMenuExData *mdata;

  mdata = new CMenuExData;
  mdata->menuIconNormal = -1;
  mdata->xoffset=-1;
  #ifdef UNICODE
  mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
  #else
  mdata->SetAnsiString(string);
  #endif
  mdata->nFlags = nFlags;
  mdata->nID = nID;
  
  
  if (nFlags&MF_OWNERDRAW){
    ASSERT(!(nFlags&MF_STRING));
    ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
  }
  else if (nFlags&MF_STRING){
    ASSERT(!(nFlags&MF_OWNERDRAW));
    ModifyMenu(pos,nFlags,nID,mdata->GetString());
  }
  else{
    ASSERT(nFlags&MF_SEPARATOR);
    ModifyMenu(pos,nFlags,nID);
  }

  return(mdata);
};

BOOL CMenuEx::LoadToolbars(const UINT *arID,int n)
{
  ASSERT(arID);
  BOOL bRet=TRUE;
  for(int i=0;i<n;++i)
    bRet |= LoadToolbar(arID[i]);
  return(bRet);
}

BOOL CMenuEx::LoadToolbar(UINT nToolBar)
{
  UINT nID;
  BOOL returnflag=FALSE;
  CToolBar bar;

  bar.Create(AfxGetMainWnd());
  if(bar.LoadToolBar(nToolBar)){
    for(int i=0;i<bar.GetCount();++i){
      nID = bar.GetItemID(i); 
      if(nID && GetMenuState(nID, MF_BYCOMMAND)
        !=0xFFFFFFFF)ModifyODMenu(NULL,nID,nToolBar);
    }
    returnflag=TRUE;
  }
  return(returnflag);
}

BOOL CMenuEx::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
{
  int xset,offset;
  UINT nStyle;
  BOOL returnflag=FALSE;
  CToolBar bar;

  bar.Create(AfxGetMainWnd());
  if(bar.LoadToolBar(nToolBar)){
    offset=bar.CommandToIndex(nID);
    if(offset>=0){
      bar.GetButtonInfo(offset,nID,nStyle,xset);
      if(xset>0)xoffset=xset;
      returnflag=TRUE;
    }
  }
  return(returnflag);
}

CMenuEx *CMenuEx::FindMenuOption(int nId,int& nLoc)
{
  int i;
  CMenuEx *psubmenu,*pgoodmenu;

  for(i=0;i<(int)(CMenu::GetMenuItemCount());++i){
#ifdef _CPPRTTI 
	  psubmenu=dynamic_cast<CMenuEx *>(CMenu::GetSubMenu(i));
#else
    psubmenu=(CMenuEx *)CMenu::GetSubMenu(i);
#endif
    if(psubmenu){
      pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
      if(pgoodmenu)return(pgoodmenu);
    }
    else if(nId==(int)GetMenuItemID(i)){
      nLoc=i;
      return(this);
    }
  }
  nLoc = -1;
  return(NULL);
}

CMenuExData *CMenuEx::FindMenuOption(wchar_t *lpstrText)
{
  int i;
  CMenuEx *psubmenu;
  CMenuExData *pmenulist;

  for(i=0;i<(int)(CMenu::GetMenuItemCount());++i){
#ifdef _CPPRTTI 
    psubmenu=dynamic_cast<CMenuEx *>(CMenu::GetSubMenu(i));
#else
    psubmenu=(CMenuEx *)CMenu::GetSubMenu(i);
#endif
    if(psubmenu){
      pmenulist=psubmenu->FindMenuOption(lpstrText);
      if(pmenulist)return(pmenulist);
    }
    else{
      const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
      for(i=0;i<=m_MenuList.GetUpperBound();++i){     
        szWide = m_MenuList[i]->GetWideString ();
        if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
          return(m_MenuList[i]);
      }
    }
  }
  return(NULL);
}


BOOL CMenuEx::LoadMenu(int nResource)
{
  return(CMenuEx::LoadMenu(MAKEINTRESOURCE(nResource)));
};

BOOL CMenuEx::LoadMenu(LPCTSTR lpszResourceName)
{
	//DestroyMenu();
	if(!PreLoadMenu(lpszResourceName)) return FALSE;
	return PostLoadMenu();
}

void CMenuEx::InsertSpaces(void)
{
  int i,j,numitems,maxlength;
  CString string,newstring;
  CSize t;
  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)); 
  m_lf =  nm.lfMenuFont;
  m_fontMenu.CreateFontIndirect (&m_lf);

  CWnd *pWnd = AfxGetMainWnd();  
  CDC *pDC = pWnd->GetDC();
  CFont* pFont = pDC->SelectObject (&m_fontMenu);
  
  numitems=CMenu::GetMenuItemCount();
  maxlength = -1;
  for(i=0;i<numitems;++i){
    string=m_MenuList[i]->GetString();
    j=string.Find((char)9);
    newstring.Empty();
    if(j!=-1)newstring.Left(j);
    else newstring=string;
    newstring+=_T(" ");//SK: modified for Unicode correctness. 
    LPCTSTR lpstrText = (LPCTSTR)newstring;
    t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
    if(t.cx>maxlength)maxlength = t.cx;
  }
  for(i=0;i<numitems;++i){
    string=m_MenuList[i]->GetString();

    j=string.Find((char)9);
    if(j!=-1){
      newstring.Empty();
      newstring=string.Left(j);
      LPCTSTR lpstrText = (LPCTSTR)(newstring);
      t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
      while(t.cx<maxlength){
        newstring+=_T(' ');//SK: modified for Unicode correctness
        LPCTSTR lpstrText = (LPCTSTR)(newstring);
        t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
      }
      newstring+=string.Mid(j);
#ifdef UNICODE      
      m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
#else
      m_MenuList[i]->SetAnsiString(newstring);
#endif
    }
  }
  pDC->SelectObject (pFont);              // Select old font in
  AfxGetMainWnd()->ReleaseDC(pDC);       // Release the DC
  m_fontMenu.DeleteObject();

⌨️ 快捷键说明

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