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

📄 bcmenu.cpp

📁 《深入剖析visual c++编程技术vcCode(人民邮电)》的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      if(nID && GetMenuState(nID, MF_BYCOMMAND)
        !=0xFFFFFFFF){
        ModifyODMenu(NULL,nID,nToolBar);
      }
    }
    returnflag=TRUE;
  }
  return(returnflag);
}

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

// O.S.
BCMenuData *BCMenu::FindMenuItem(UINT nID)
{
  BCMenuData *pData = NULL;
  int i;

  for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
    if (m_MenuList[i]->nID == nID){
      pData = m_MenuList[i];
      break;
    }
  }
  if (!pData){
    int loc;
    BCMenu *pMenu = FindMenuOption(nID, loc);
    ASSERT(pMenu != this);
    if (loc >= 0){
      return pMenu->FindMenuItem(nID);
    }
  }
  return pData;
}

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

  for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI 
    psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
#else
    psubmenu=(BCMenu *)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);
}

BCMenuData *BCMenu::FindMenuOption(wchar_t *lpstrText)
{
  int i,j;
  BCMenu *psubmenu;
  BCMenuData *pmenulist;

  for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI 
    psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
#else
    psubmenu=(BCMenu *)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(j=0;j<=m_MenuList.GetUpperBound();++j){     
        szWide = m_MenuList[j]->GetWideString ();
        if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
          return(m_MenuList[j]);
      }
    }
  }
  return(NULL);
}


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

BOOL BCMenu::LoadMenu(LPCTSTR lpszResourceName)
{
  TRACE(_T(
    "IMPORTANT:Use BCMenu::DestroyMenu to destroy Loaded Menu's\n"));
  ASSERT_VALID(this);
  ASSERT(lpszResourceName != NULL);

  // Find the Menu Resource:
  HINSTANCE m_hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
  HRSRC hRsrc = ::FindResource(m_hInst,lpszResourceName,RT_MENU);
  if(hRsrc == NULL)return FALSE;

  // Get size of resource:

  DWORD dwSize = SizeofResource(NULL, hRsrc);

  // Load the Menu Resource:

  HGLOBAL hGlobal = LoadResource(m_hInst, hRsrc);
  if(hGlobal == NULL)return FALSE;

  // Attempt to create us as a menu...

  if(!CMenu::CreateMenu())return FALSE;

  // Get Item template Header, and calculate offset of MENUITEMTEMPLATES

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


  // Variables needed during processing of Menu Item Templates:

  int j=0;
  BCMenuData*  pData = NULL;              // New OD Menu Item Data
  WORD    dwFlags = 0;              // Flags of the Menu Item
  WORD    dwID  = 0;              // ID of the Menu Item
  UINT    uFlags;                  // Actual Flags.
  wchar_t *szCaption=NULL;
  int      nLen   = 0;                // Length of caption
  CTypedPtrArray<CPtrArray, BCMenu*>  m_Stack;    // Popup menu stack
  CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
  m_Stack.Add(this);                  // Add it to this...
  m_StackEnd.Add(FALSE);

  do{
    // Obtain Flags and (if necessary), the ID...
    memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
    if(!(dwFlags & MF_POPUP)){
      memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
      pTp+=sizeof(WORD);
    }
    else dwID = 0;

    uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
    if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
      uFlags -= MF_END;

    // Obtain Caption (and length)

    nLen = 0;
    char *ch = (char*)pTp;
    szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
    wcscpy(szCaption,(wchar_t *)pTp);
    pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
    
    // Handle popup menus first....

    //WideCharToMultiByte
    if(dwFlags & MF_POPUP){
      if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
      BCMenu* pSubMenu = new BCMenu;
      pSubMenu->m_unselectcheck=m_unselectcheck;
      pSubMenu->m_selectcheck=m_selectcheck;
      pSubMenu->checkmaps=checkmaps;
      pSubMenu->checkmapsshare=TRUE;
      pSubMenu->CreatePopupMenu();

      // Append it to the top of the stack:

      m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
        (UINT)pSubMenu->m_hMenu, -1);
      m_Stack.Add(pSubMenu);
      m_StackEnd.Add(FALSE);
    }
    else {
      m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
        dwID, -1);
      if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
      j = m_Stack.GetUpperBound();
      while(j>=0 && m_StackEnd.GetAt(j)){
        m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
        m_Stack.RemoveAt(j);
        m_StackEnd.RemoveAt(j);
        --j;
      }
    }

    delete[] szCaption;
  }while(m_Stack.GetUpperBound() != -1);

  for(int i=0;i<(int)GetMenuItemCount();++i){
    CString str=m_MenuList[i]->GetString();

    if(GetSubMenu(i)){
      m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
      ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
        (UINT)GetSubMenu(i)->m_hMenu,str);
    }
    else{
      m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
      ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
    }
  }
  
  return(TRUE);
}

void BCMenu::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=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=string.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();
}

void BCMenu::LoadCheckmarkBitmap(int unselect, int select)
{
  if(unselect>0 && select>0){
    m_selectcheck=select;
    m_unselectcheck=unselect;
    if(checkmaps)checkmaps->DeleteImageList();
    else checkmaps=new(CImageList);
    checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
    BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
    BOOL flag2=AddBitmapToImageList(checkmaps,select);
		if(!flag1||!flag2){
			checkmaps->DeleteImageList();
			delete checkmaps;
			checkmaps=NULL;
    }
  }
}

//--------------------------------------------------------------------------
//[18.06.99 rj]
BOOL BCMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
{
	BOOL returnflag=FALSE;

	if(MF_BYPOSITION&nFlags){
		UINT numMenuItems = m_MenuList.GetUpperBound();
		if(id<=numMenuItems){
			string=m_MenuList[id]->GetString();
			returnflag=TRUE;
		}
	}
	else{
		int uiLoc;
		BCMenu* pMenu = FindMenuOption(id,uiLoc);
		if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
	}
	return(returnflag);
}


void BCMenu::DrawRadioDot(CDC *pDC,int x,int y,COLORREF color)
{
  CRect rcDot(x,y,x+6,y+6);
  CBrush brush;
  CPen pen;
  brush.CreateSolidBrush(color);
  pen.CreatePen(PS_SOLID,0,color);
  CBrush *pOldBrush=pDC->SelectObject(&brush);
  CPen *pOldPen=pDC->SelectObject(&pen);
  pDC->Ellipse(&rcDot);
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
  pen.DeleteObject();
  brush.DeleteObject();
}

void BCMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color)
{
  pDC->SetPixel(x,y+2,color);
  pDC->SetPixel(x,y+3,color);
  pDC->SetPixel(x,y+4,color);

  pDC->SetPixel(x+1,y+3,color);
  pDC->SetPixel(x+1,y+4,color);
  pDC->SetPixel(x+1,y+5,color);

  pDC->SetPixel(x+2,y+4,color);
  pDC->SetPixel(x+2,y+5,color);
  pDC->SetPixel(x+2,y+6,color);

  pDC->SetPixel(x+3,y+3,color);
  pDC->SetPixel(x+3,y+4,color);
  pDC->SetPixel(x+3,y+5,color);

  pDC->SetPixel(x+4,y+2,color);
  pDC->SetPixel(x+4,y+3,color);
  pDC->SetPixel(x+4,y+4,color);

  pDC->SetPixel(x+5,y+1,color);
  pDC->SetPixel(x+5,y+2,color);
  pDC->SetPixel(x+5,y+3,color);

  pDC->SetPixel(x+6,y,color);
  pDC->SetPixel(x+6,y+1,color);
  pDC->SetPixel(x+6,y+2,color);
}

BCMenuData *BCMenu::FindMenuList(UINT nID)
{
  for(int i=0;i<=m_MenuList.GetUpperBound();++i){
    if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
      m_MenuList[i]->syncflag=1;
      return(m_MenuList[i]);
    }
  }
  return(NULL);
}

void BCMenu::InitializeMenuList(int value)
{
  for(int i=0;i<=m_MenuList.GetUpperBound();++i)
    m_MenuList[i]->syncflag=value;
}

void BCMenu::DeleteMenuList(void)
{
  for(int i=0;i<=m_MenuList.GetUpperBound();++i){
    if(!m_MenuList[i]->syncflag){
      delete m_MenuList[i];
    }
  }
}

void BCMenu::SynchronizeMenu(void)
{
  CTypedPtrArray<CPtrArray, BCMenuData*> temp;
  BCMenuData *mdata;
  CString string;
  UINT submenu,nID=0,state,j;

  InitializeMenuList(0);
  for(j=0;j<GetMenuItemCount();++j){
    mdata=NULL;
    state=GetMenuState(j,MF_BYPOSITION);
    if(state&MF_POPUP){
      submenu=(UINT)GetSubMenu(j)->m_hMenu;
      mdata=FindMenuList(submenu);
      GetMenuString(j,string,MF_BYPOSITION);
      if(!mdata)mdata=NewODMenu(j,
        (state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
      else if(string.GetLength()>0)
#ifdef UNICODE
        mdata->SetWideString(string);  //SK: modified for dynamic allocation
#else
        mdata->SetAnsiString(string);
#endif
    }
    else if(state&MF_SEPARATOR){
      mdata=FindMenuList(0);
      if(!mdata)mdata=NewODMenu(j,
        state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
      else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
    }
    else{
      nID=GetMenuItemID(j);
      mdata=FindMenuList(nID);
      GetMenuString(j,string,MF_BYPOSITION);
      if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
        nID,string);
      else{
        mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
        if(string.GetLength()>0)
#ifdef UNICODE
		    mdata->SetWideString(string);//SK: modified for dynamic allocation
#else
            mdata->SetAnsiString(string);
#endif
            
        ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
      }
    }
    if(mdata)temp.Add(mdata);
  }
  DeleteMenuList();
  m_MenuList.RemoveAll();
  m_MenuList.Append(temp);
  temp.RemoveAll(); 
}

void BCMenu::UpdateMenu(CMenu *pmenu)
{
#ifdef _CPPRTTI 
  BCMenu *psubmenu = dynamic_cast<BCMenu *>(pmenu);
#else
  BCMenu *psubmenu = (BCMenu *)pmenu;
#endif
  if(psubmenu)psubmenu->SynchronizeMenu();
}

LRESULT BCMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
                                     CMenu *pMenu)
{
#ifdef _CPPRTTI 
  BCMenu *pBCMenu = dynamic_cast<BCMenu *>(pMenu);
#else
  BCMenu *pBCMenu = (BCMenu *)pMenu;
#endif
  if(pBCMenu && nFlags&MF_POPUP){
    CString key(_T('&'),2);//SK: modified for Unicode correctness
	key.SetAt(1,(TCHAR)nChar);
	key.MakeLower();
    CString menutext;

⌨️ 快捷键说明

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