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

📄 coolmenu.cpp

📁 一个简单的sniffer,下载后请用winrar
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		}

		// compute text rectangle and colors
		CRect rcText = rcItem;				 // start w/whole item
		rcText.left += cxButn + CXGAP + CXTEXTMARGIN; // left margin
		rcText.right -= cxButn;				 // right margin
		dc.SetBkMode(TRANSPARENT);			 // paint transparent text
		COLORREF colorText = GetSysColor(bDisabled ?  COLOR_GRAYTEXT :
			bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);

		// Now paint menu item text.	No need to select font,
		// because windows sets it up before sending WM_DRAWITEM
		//
		if(bDisabled && bSelected && colorText == colorBG)
		{
			colorText = GetSysColor(COLOR_3DLIGHT);
		}

		if (bDisabled && (!bSelected || colorText == colorBG))
		{
			// disabled: draw hilite text shifted southeast 1 pixel for embossed
			// look. Don't do it if item is selected, tho--unless text color same
			// as menu highlight color. Got it?
			//
			DrawMenuText(dc, rcText + CPoint(1,1), pmd->text,
				GetSysColor(COLOR_3DHILIGHT));
		}
		DrawMenuText(dc, rcText, pmd->text, colorText); // finally!
	}
	dc.Detach();

	return TRUE; // handled
}

/////////////////
// Helper function to draw justified menu text. If the text contains a TAB,
// draw everything after the tab right-aligned
//
void CCoolMenuManager::DrawMenuText(CDC& dc, CRect rc, CString text,
	COLORREF color)
{
	CString left = text;
	CString right;
	int iTabPos = left.Find('\t');
	if (iTabPos >= 0)
	{
		right = left.Right(left.GetLength() - iTabPos - 1);
		left  = left.Left(iTabPos);
	}
	dc.SetTextColor(color);
	dc.DrawText(left, &rc, DT_MYSTANDARD);
	if (iTabPos > 0)
		dc.DrawText(right, &rc, DT_MYSTANDARD|DT_RIGHT);
}

#ifndef OBM_CHECK
#define OBM_CHECK 32760 // from winuser.h
#endif

//////////////////
// Draw 3D checkmark
//
//		dc				device context to draw in
//		rc				rectangle to center bitmap in
//		bSelected		TRUE if button is also selected
//		hbmCheck		Checkmark bitmap to use, or NULL for default
//
BOOL CCoolMenuManager::Draw3DCheckmark(CDC& dc, const CRect& rc,
	BOOL bSelected, HBITMAP hbmCheck)
{
	// get checkmark bitmap if none, use Windows standard or loaded checkmarks
	if (!hbmCheck)
	{
		CBitmap bm;
		//Vytukas additions
		if(bSelected)
		{
			if(m_CheckSelected != -1)
				VERIFY(bm.LoadBitmap(m_CheckSelected));
		}
		else
		{
			if(m_CheckUnselected != -1)
				VERIFY(bm.LoadBitmap(m_CheckUnselected));
		}

		if(!(HBITMAP)bm)
			VERIFY(bm.LoadOEMBitmap(OBM_CHECK));

		hbmCheck = (HBITMAP)bm.Detach();
		ASSERT(hbmCheck);
	}
	
	// center bitmap in caller's rectangle
	BITMAP bm;
	::GetObject(hbmCheck, sizeof(bm), &bm);
	int cx = bm.bmWidth;
	int cy = bm.bmHeight;
	CRect rcDest = rc;
	CPoint p(0,0);
	CSize delta(CPoint((rc.Width() - cx)/2, (rc.Height() - cy)/2));
	if (rc.Width() > cx)
		rcDest = CRect(rc.TopLeft() + delta, CSize(cx, cy));
	else
		p -= delta;

	// select checkmark into memory DC
	CDC memdc;
	memdc.CreateCompatibleDC(&dc);
	HBITMAP hOldBM = (HBITMAP)::SelectObject(memdc, hbmCheck);

	// set BG color based on selected state
	COLORREF colorOld =
		dc.SetBkColor(GetSysColor(bSelected ? COLOR_MENU : COLOR_3DLIGHT));
	dc.BitBlt(rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
		&memdc, p.x, p.y, MERGECOPY);
	dc.SetBkColor(colorOld);

	::SelectObject(memdc, hOldBM); // restore

	// draw pushed-in hilight.
	if (rc.Width() > cx)			// if room:
		rcDest.InflateRect(1,1);	// inflate checkmark by one pixel all around
	dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);

	return TRUE;
}

//////////////////
// Handle WM_INITMENUPOPUP on behalf of frame.
//
void CCoolMenuManager::OnInitMenuPopup(CMenu* pMenu,
	UINT nIndex, BOOL bSysMenu)
{
	if (m_bAutoAccel)
	{
		// check for new accels. If ASSERT bombs, you forgot to call Install.
		ASSERT_VALID(m_pFrame);
		HACCEL hAccel = m_pFrame->GetDefaultAccelerator();
		if (hAccel != m_hAccel)
			LoadAccel(hAccel);
	}
	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 = offset of prev, or 0
			ac.cmd = 0;
			if(pAccel)
			{
				ac.cmd = (WORD)(&ac - pAccel);
			}
		}
	}
}

//////////////////
// 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);

	CString sItemName;

	UINT nItem = pMenu->GetMenuItemCount();
	for (UINT i = 0; i < nItem; i++) 
	{	// loop over each item in menu
		// get menu item info
		char itemname[256];
		CMenuItemInfo info;
		info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID | MIIM_TYPE;
		info.dwTypeData = itemname;
		info.cch = sizeof(itemname);
		::GetMenuItemInfo(*pMenu, i, TRUE, &info);
		CMyItemData* pmd = (CMyItemData*)info.dwItemData;

		if (pmd && !pmd->IsMyItemData())
		{
			CMTRACE(_T("CCoolMenuManager: ignoring foreign owner-draw item\n"));
			continue; // owner-draw menu item isn't mine--leave it alone
		}

		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 (bShowButtons)
		{
			// 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)
				{									// if no item data:
					pmd = new CMyItemData;				//   create one
					ASSERT(pmd);							//   (I hope)
					pmd->fType = info.fType;			//   handy when drawing
					pmd->iButton = GetButtonIndex((WORD)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
			}

			// now add the menu to list of "converted" menus
			HMENU hmenu = pMenu->GetSafeHmenu();
			ASSERT(hmenu);
			if (!m_menuList.Find(hmenu))
				m_menuList.AddHead(hmenu);

			// 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

			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 = NULL;				// item data is NULL
				info.fMask |= MIIM_DATA;			// change it
				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
				strncpy(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, i, TRUE, &info);
		}
	}
	nIndex;
}

//////////////////
// 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);

	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('&');
			if (iAmpersand >=0 && toupper(nChar)==toupper(text[iAmpersand+1]))
				arItemsMatched.Add(i);
		}
		if (info.fState & MFS_HILITE)
			iCurrentItem = i; // note index of current item
	}

	// arItemsMatched now contains indexes of items that match the char typed.
	//
	//   * if none: beep
	//   * if one:  execute it
	//   * if more than one: hilite next
	//
	UINT nFound = arItemsMatched.GetSize();
	if (nFound == 0)
		return 0;

	else if (nFound==1)
		return MAKELONG(arItemsMatched[0], MNC_EXECUTE);

	// more than one found--return 1st one past current selected item;
	UINT iSelect = 0;
	for (i=0; i < nFound; i++)
	{
		if (arItemsMatched[i] > iCurrentItem)
		{
			iSelect = i;
			break;
		}
	}

	nFlags;
	return MAKELONG(arItemsMatched[iSelect], MNC_SELECT);
}

//////////////////
// Handle WM_MENUSELECT: check for menu closed
//
void CCoolMenuManager::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
	if (hSysMenu==NULL && nFlags==0xFFFF)
	{
		// Windows has closed the menu: restore all menus to original state
		while (!m_menuList.IsEmpty())
		{
			ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()),
				0, FALSE, FALSE);
		}
	}
	nItemID;
}

//////////////////
// Append the name of accelerator for given command ID to menu string.
// sItemName is menu item name, which will have the accelerator appended.
// For example, might call with sItemName = "File &Open" and return with
// sItemName = "File &Open\tCtrl-O". Returns BOOL = whether string changed.
//
BOOL CCoolMenuManager::AppendAccelName(CString& sItemName, UINT nID)
{
	int iTabPos = sItemName.Find('\t');
	if (iTabPos > 0)
		sItemName = sItemName.Left(iTabPos);

	BOOL bFound = FALSE;
	for (ACCEL* pa = GetAccel((WORD)nID); pa; pa -= pa->cmd)
	{
		sItemName += bFound ? _T(", ") : _T("\t");
		if (pa->fVirt & FALT)
			sItemName += _T("Alt+");
		if (pa->fVirt & FCONTROL)
			sItemName += _T("Ctrl+");
		if (pa->fVirt & FSHIFT)	
			sItemName += _T("Shift+");
		if (pa->fVirt & FVIRTKEY)
		{
			TCHAR keyname[64];
			UINT vkey = MapVirtualKey(pa->key, 0)<<16;
			GetKeyNameText(vkey, keyname, sizeof(keyname));
			sItemName += keyname;
		}
		else
			sItemName += (char)pa->key;

		bFound = TRUE;
		if (pa->cmd == 0)
			break;
	}
	return bFound;
}

//////////////////
// This function fixes MFC's diseased dot bitmap used for
// "radio-style" menu items (CCmdUI->SetRadio), which is completely
// wrong if the menu font is large. 
//
void CCoolMenuManager::FixMFCDotBitmap()
{
	HBITMAP hbmDot = GetMFCDotBitmap();
	if (hbmDot)
	{
		// Draw a centered dot of appropriate size
		BITMAP bm;
		::GetObject(hbmDot, sizeof(bm), &bm);
		CRect rcDot(0,0, bm.bmWidth, bm.bmHeight);
		rcDot.DeflateRect((bm.bmWidth>>1)-2, (bm.bmHeight>>1)-2);

		CWindowDC dcScreen(NULL);
		CDC memdc;
		memdc.CreateCompatibleDC(&dcScreen);
		int nSave = memdc.SaveDC();
		memdc.SelectStockObject(BLACK_PEN);
		memdc.SelectStockObject(BLACK_BRUSH);
		memdc.SelectObject((HGDIOBJ)hbmDot);
		memdc.PatBlt(0, 0, bm.bmWidth, bm.bmHeight, WHITENESS);
		memdc.Ellipse(&rcDot);
		memdc.RestoreDC(nSave);
	}
}

//////////////////
// This function gets MFC's dot bitmap.
//
HBITMAP CCoolMenuManager::GetMFCDotBitmap()
{
	// The bitmap is stored in afxData.hbmMenuDot, but afxData is MFC-private,
	// so the only way to get it is create a menu, set the radio check,
	// and then see what bitmap MFC set in the menu item.
	CMenu menu;
	VERIFY(menu.CreateMenu());
	VERIFY(menu.AppendMenu(MFT_STRING, 0, (LPCTSTR)NULL));
	CCmdUI cui;
	cui.m_pMenu = &menu;
	cui.m_nIndex = 0;
	cui.m_nIndexMax = 1;
	cui.SetRadio(TRUE);
	CMenuItemInfo info;
	info.fMask = MIIM_CHECKMARKS;
	GetMenuItemInfo(menu, 0, MF_BYPOSITION, &info);
	HBITMAP hbmDot = info.hbmpChecked;
	menu.DestroyMenu();
	return hbmDot;
}

⌨️ 快捷键说明

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