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

📄 uicoolmenu.cpp

📁 vc座的资源管理器源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    if (!bSysMenu) {
      ConvertMenu(pMenu, nIndex, bSysMenu, m_bShowButtons);
    }
  }
  ConvertMenu(pMenu, nIndex, bSysMenu, m_bShowButtons);
}

//////////////////
// Set the accelerator table used to generate automatic key
// names in menus. Delete previous table if any.
//
void CCoolMenuManager::LoadAccel(HACCEL hAccel)
{
  DestroyAccel();
  int nAccel;
  if (hAccel && (nAccel = CopyAcceleratorTable(hAccel, NULL, 0)) > 0) {
    m_pAccel = new ACCEL [nAccel];
    ASSERT(m_pAccel);
    CopyAcceleratorTable(hAccel, m_pAccel, nAccel);

    // Now I have the accelerators. Look over list, linking each command
    // ID with its ACCEL structure--i.e., m_mapIDtoAccel[nID] = ACCEL for
    // that ID. If more than one ACCEL for a given command (command has more
    // than one shortcut), fix up so ACCEL.cmd is offset of prev ACCEL
    // 
    for (int i=0; i<nAccel; i++) {
      ACCEL& ac = m_pAccel[i];
      ACCEL* pAccel = GetAccel(ac.cmd);
      m_mapIDtoAccel.SetAt(ac.cmd, &ac);
      ac.cmd = pAccel ? &ac - pAccel : 0; // ac.cmd = offset of prev, or 0
    }
  }
}

void CCoolMenuManager::ConvertMenu(CMenu *pMenu)
{
    ConvertMenu(pMenu, 0, FALSE, TRUE);
}

void CCoolMenuManager::UnconvertMenu(CMenu *pMenu)
{
    ConvertMenu(pMenu, 0, FALSE, FALSE);
}

void CCoolMenuManager::ConvertMenuItem(CMenu *pMenu, int iIndex, 
    bool bRecurse /*= true*/, bool bUnconvert /*= false*/)
{
    ASSERT_VALID(pMenu);
    CString   sItemName;

    // get menu item info
    TCHAR itemname[_MAX_PATH];
    CMenuItemInfo info;
    info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID | MIIM_TYPE;
    info.dwTypeData = itemname;
    info.cch = sizeof(itemname);
    ::GetMenuItemInfo(*pMenu, iIndex, TRUE, &info);
    
    // O.S. - ignore separators
    if (info.fType & MFT_SEPARATOR)
        return;

    CMyItemData* pmd = (CMyItemData*)info.dwItemData;
    // O.S. - recurse sub-menus
    if (bRecurse && info.hSubMenu)
    {
        ConvertMenu(pMenu->GetSubMenu(iIndex), 0, FALSE, !bUnconvert);
    }
    
    if ((info.fType & MFT_OWNERDRAW)  && pmd  &&  !pmd->IsMyItemData()) {
        CMTRACE(_T("CCoolMenuManager: ignoring foreign owner-draw item\n"));
        return;
        // owner-draw menu item isn't mine--leave it alone
    }
    
/*    // Koji MATSUNAMI 1999.2.23
    //
    if (bSysMenu && info.wID >= 0xF000) {
        CMTRACE(_T("CCoolMenuManager: ignoring sys menu item\n"));
        continue; // don't do for system menu commands
    }
*/    
    // now that I have the info, I will modify it
    info.fMask = 0; // assume nothing to change
    
    if (!bUnconvert) 
    {
        // I'm showing buttons: convert to owner-draw
        
        if (!(info.fType & MFT_OWNERDRAW))
		{
            // If not already owner-draw, make it so. NOTE: If app calls
            // pCmdUI->SetText to change the text of a menu item, MFC will
            // turn the item to MFT_STRING. So I must set it back to
            // MFT_OWNERDRAW again. In this case, the menu item data (pmd)
            // will still be there.
            // 
            info.fType |= MFT_OWNERDRAW;
            info.fMask |= MIIM_TYPE;
            if (!pmd || (pmd && !pmd->IsMyItemData()))
			{                   // if no item data:
				if (pmd && !pmd->IsMyItemData())
				{
					CMyItemData* pnmd = new CMyItemData;    //   create one
					pnmd->pContext = pmd;
					pmd = pnmd;
				}
				else
					pmd = new CMyItemData;    //   create one
                ASSERT(pmd);              //   (I hope)
                pmd->fType = info.fType;  //   handy when drawing
                if (info.hSubMenu)
                {
                    int nID;
                    if (m_mapHMENUtoID.Lookup((void *)info.wID, (WORD&)nID))
                    {
                        pmd->iButton = GetButtonIndex(nID);
                    }
                    else
                    {
                        pmd->iButton = -1;
                    }
                }
                else
                    pmd->iButton = GetButtonIndex(info.wID);
                
                info.dwItemData = (DWORD)pmd;   //   set in menu item data
                info.fMask |= MIIM_DATA;      //   set item data
            }
            pmd->text = info.dwTypeData;      // copy menu item string

            // append accelerators to menu item name
            if (m_pAccel && m_bAutoAccel)
                AppendAccelName(pmd->text, info.wID);
        }
   } 
   else 
   {
        // no buttons -- I'm converting to strings
        
        if (info.fType & MFT_OWNERDRAW)  // if ownerdraw:
        { 
            info.fType &= ~MFT_OWNERDRAW;   //   turn it off
            info.fMask |= MIIM_TYPE;        //   change item type
            ASSERT(pmd);                    //   sanity check
            sItemName = pmd->text;          //   save name before deleting pmd
        } 
        else                    // otherwise: 
        {
            sItemName = info.dwTypeData;    //   use name from MENUITEMINFO
            pmd       = NULL;
        }
        
        if (pmd) {
            // NOTE: pmd (item data) could still be left hanging around even
            // if MFT_OWNERDRAW is not set, in case mentioned above where app
            // calls pCmdUI->SetText to set text of item and MFC sets the type
            // to MFT_STRING.
            //
            info.dwItemData = (DWORD)pmd->pContext; // item data<-user's context
            info.fMask |= MIIM_DATA;                // change it
            safe_delete(pmd);                       // and item data too
        }
        
        // possibly add accelerator name
        if (m_pAccel  && m_bAutoAccel && AppendAccelName(sItemName, info.wID))
            info.fMask |= MIIM_TYPE;      //  change item type (string)
        
        if (info.fMask & MIIM_TYPE) {
            // if setting name, copy name from CString to buffer and set cch
            _tcsncpy(itemname, sItemName, sizeof(itemname));
            info.dwTypeData = itemname;
            info.cch = sItemName.GetLength();
        }
    }
    
    // if after all the above, there is anything to change, change it
    if (info.fMask) {
        CMTRACE(_T("Converting '%s' to %s\n"), itemname,
            (info.fType & MFT_OWNERDRAW) ? _T("OWNERDRAW") : _T("STRING"));
        SetMenuItemInfo(*pMenu, iIndex, TRUE, &info);
    }
}

///////////////////////
// Addition: Philip Oldaker
DWORD CCoolMenuManager::SwitchContextItemData(CMenu *pMenu, int iCmd, DWORD dwItemData /*0*/, BOOL bByPosition /*TRUE*/)
{
	CMyItemData* pmd = GetMyItemData(*pMenu,iCmd,bByPosition);
	DWORD dwData=0;	
	if (pmd == NULL)
		return dwData;
	CMenuItemInfo info;
    info.fMask |= MIIM_DATA;                // change it
	if (pmd->IsMyItemData())
	{
		dwData= (DWORD)pmd;
        info.dwItemData = (DWORD)pmd->pContext;
        SetMenuItemInfo(*pMenu, iCmd, bByPosition, &info);
	}
	else if (dwItemData)
	{
		CMyItemData *pMyItemData = (CMyItemData*)dwItemData;
		if (pMyItemData->IsMyItemData())
		{
	        info.dwItemData = dwItemData;
		    SetMenuItemInfo(*pMenu, iCmd, bByPosition, &info);
		}
	}
	return dwData;
}
// This may not be the best way of doing it but it seems to work
// Just save the IContextMenu2 pointer on behalf of the windows shell
// and create new item data
void CCoolMenuManager::AddShellContextMenu(CMenu *pMenu, LPCONTEXTMENU lpm, int iIndex)
{
	CMyItemData* pmd = GetMyItemData(*pMenu,iIndex,TRUE);
	if (pmd == NULL || !pmd->IsMyItemData())
	{
		DWORD dw = (DWORD)pmd;
		pmd = new CMyItemData;
		pmd->pContext = (void*)dw;
	}
	pmd->lpcm = lpm;
	pmd->lpcm->AddRef();
    SetMyItemData(pmd,*pMenu,iIndex,TRUE);
}

///////////////////////////////

//////////////////
// This rather gnarly function is used both to convert the menu from strings to
// owner-draw and vice versa. In either case, it also appends automagic
// accelerator key names to the menu items, if m_bAutoAccel is TRUE.
//
void CCoolMenuManager::ConvertMenu(CMenu* pMenu, UINT nIndex, 
                                   BOOL bSysMenu, BOOL bShowButtons)
{
    ASSERT_VALID(pMenu);
    
    UINT i, nItem;

    // add/remove the menu to/from list of "converted" menus
    HMENU hmenu = pMenu->GetSafeHmenu();
    ASSERT(hmenu);
    POSITION p = m_menuList.Find(hmenu);
    if (!p)
    {
        if (bShowButtons)
            m_menuList.AddHead(hmenu);
    }
    else
    {
        if (!bShowButtons)
            m_menuList.RemoveAt(p);
    }
    
    nItem = pMenu->GetMenuItemCount();    

    for (i = 0; i < nItem; i++) 
    {  
        // loop over each item in menu
        ConvertMenuItem(pMenu, i, true, !bShowButtons);
    }
}

void *CCoolMenuManager::SetItemData(HMENU hMenu, void *pData, UINT uItem, BOOL bByPosition /*= FALSE*/)
{
    CMyItemData *pmd = GetMyItemData(hMenu, uItem, bByPosition);
    ASSERT(pmd->IsMyItemData());
    void *pOld = pmd->pContext;
    pmd->pContext = pData;
    SetMyItemData(pmd, hMenu, uItem, bByPosition);
    return pOld;
}

void *CCoolMenuManager::GetItemData(HMENU hMenu, UINT uItem, BOOL bByPosition /*= FALSE*/)
{
    MENUITEMINFO mii;
    mii.cbSize     = sizeof(mii);
    mii.fMask      = MIIM_DATA | MIIM_TYPE;
    mii.dwTypeData = NULL;
    mii.cch        = 0;
    if (!::GetMenuItemInfo(hMenu, uItem, bByPosition, &mii))
        return NULL;
if (mii.dwItemData == -1) _asm int 3;    
    CMyItemData *pmd = (CMyItemData *)mii.dwItemData;
    if ((mii.fType & MFT_OWNERDRAW)  &&  pmd  &&  pmd->IsMyItemData())
        return pmd->pContext;

    return pmd;
}

HICON CCoolMenuManager::SetItemIcon(HMENU hMenu, HICON hIcon, UINT uItem, BOOL bByPosition /*= FALSE*/)
{
    CMyItemData *pmd = GetMyItemData(hMenu, uItem, bByPosition);
    ASSERT(pmd->IsMyItemData());
    HICON hOldIcon = pmd->hIcon;
    pmd->hIcon = hIcon;
    if (hIcon)
        pmd->iButton = USES_ICON;
    else
        pmd->iButton = -1;
    SetMyItemData(pmd, hMenu, uItem, bByPosition);
    return hOldIcon;
}

HICON CCoolMenuManager::GetItemIcon(HMENU hMenu, UINT uItem, BOOL bByPosition /*= FALSE*/)
{
    CMyItemData *pmd = GetMyItemData(hMenu, uItem, bByPosition);
    ASSERT(pmd->IsMyItemData());
    return pmd->hIcon;
}

void CCoolMenuManager::SetSubMenuIcon(HMENU hSubMenu, int nID)
{
    m_mapHMENUtoID[(void *)hSubMenu] = nID;
}

void CCoolMenuManager::UnmanageSubMenu(HMENU hSubMenu)
{
    m_mapHMENUtoID.RemoveKey((void *)hSubMenu);
}


//////////////////
// User typed a char into menu. Look for item with & preceeding the char typed.
//
LRESULT CCoolMenuManager::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu)
{
	ASSERT_VALID(pMenu);
	CMyItemData* pmd = GetMyItemData(*pMenu,0,TRUE);
	// Addition: Philip Oldaker
	// Pass it on to the shell if this has been set
	if (pmd->IsMyItemData() && pmd->lpcm)
	{
		LRESULT lResult=0;
		LPCONTEXTMENU3 lpcm3=NULL;
		HRESULT hr = pmd->lpcm->QueryInterface(IID_IContextMenu3,(LPVOID*)&lpcm3);
		if (SUCCEEDED(hr))
		{
			// convert menu back to original item data
			UINT nCount = pMenu->GetMenuItemCount();
			DWORD *pArrItemData = new DWORD[nCount];
			for(UINT i1=0;i1 < nCount;i1++)
				pArrItemData[i1] = SwitchContextItemData(pMenu,i1);
			lpcm3->HandleMenuMsg2(WM_MENUCHAR,MAKELPARAM(nChar,nFlags),(LPARAM)pMenu->GetSafeHmenu(),&lResult);
			lpcm3->Release();
			// Convert menu back to back our item data
			for(UINT i2=0;i2 < nCount;i2++)
				SwitchContextItemData(pMenu,i2,pArrItemData[i2]);
			delete []pArrItemData;
		}
		return lResult;
	}
	////////////////////////////////

  UINT iCurrentItem = (UINT)-1; // guaranteed higher than any command ID
  CUIntArray arItemsMatched;    // items that match the character typed

  UINT nItem = pMenu->GetMenuItemCount();
  for (UINT i=0; i< nItem; i++) {
    // get menu info
    CMenuItemInfo info;
    info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
    ::GetMenuItemInfo(*pMenu, i, TRUE, &info);

    CMyItemData* pmd = (CMyItemData*)info.dwItemData;
    if ((info.fType & MFT_OWNERDRAW) && pmd && pmd->IsMyItemData()) {
      CString& text = pmd->text;
      int iAmpersand = text.Find(_T('&'));
      if (iAmpersand >=0 && toupper(nChar)==toupper(text[iAmpersand+1]))
        arItemsMatched.Add(i);
    }
    if (info.fState & MFS_HILITE)

⌨️ 快捷键说明

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