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

📄 coolmenu.cpp

📁 一个很好的富文本编辑程序,类似于windows中的写字板但并不同
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		cx += m_szButton.cx<<1;		// button width (L=button; R=empty margin)

		// whatever value I return in lpms->itemWidth, Windows will add the
		// width of a menu checkmark, so I must subtract to defeat Windows. Argh.
		//
		cx -= GetSystemMetrics(SM_CXMENUCHECK)-1;
		lpms->itemWidth = cx;		// done deal

		CMTRACE(_T("OnMeasureItem for '%s':\tw=%d h=%d\n"), (LPCTSTR)pmd->text,
			lpms->itemWidth, lpms->itemHeight);
	}
	return TRUE; // handled
}

/////////////////
// Handle WM_DRAWITEM on behalf of frame. Note: in all that goes
// below, can't assume rcItem.left=0 because of multi-column menus!
//
BOOL CCoolMenuManager::OnDrawItem(LPDRAWITEMSTRUCT lpds)
{
	ASSERT(lpds);

	// Omar L Francisco
	if (lpds->CtlType != ODT_MENU)
		return FALSE;
	
	// Omar L Francisco
	CMyItemData* pmd = (CMyItemData*)lpds->itemData;
	ASSERT(pmd);
	if (!pmd->IsMyItemData())
		return FALSE;

	ASSERT(lpds->itemAction != ODA_FOCUS);
	ASSERT(lpds->hDC);
	CDC dc;
	dc.Attach(lpds->hDC);

	const CRect& rcItem = lpds->rcItem;
	if (pmd->fType & MFT_SEPARATOR) {
		// draw separator
		CRect rc = rcItem;								// copy rect
		rc.top += rc.Height()>>1;						// vertical center
		dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP);		// draw separator line

	} else {													// not a separator

		CMTRACE(_T("OnDrawItem for '%s':\tw=%d h=%d\n"), (LPCTSTR)pmd->text,
			rcItem.Width(), rcItem.Height());

		BOOL bDisabled = lpds->itemState & ODS_GRAYED;
		BOOL bSelected = lpds->itemState & ODS_SELECTED;
		BOOL bChecked  = lpds->itemState & ODS_CHECKED;
		BOOL bHaveButn=FALSE;

		// Paint button, or blank if none
		CRect rcButn(rcItem.TopLeft(), m_szButton);	// button rect
		rcButn += CPoint(0,									// center vertically
			(rcItem.Height() - rcButn.Height())>>1 );

		int iButton = pmd->iButton;
		if (iButton >= 0) {

			// this item has a button!
			bHaveButn = TRUE;

			// compute point to start drawing
			CSize sz = rcButn.Size() - m_szBitmap;
			sz.cx >>= 1;
			sz.cy >>= 1;
			CPoint p(rcButn.TopLeft() + sz);

			// draw disabled or normal
			if (!bDisabled) {
				// normal: fill BG depending on state
				PLFillRect(dc, rcButn, GetSysColor(
					(bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU));

				// draw pushed-in or popped-out edge
				if (bSelected || bChecked) {
					CRect rc2 = rcButn;
					dc.DrawEdge(rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER,
						BF_RECT);
				}
				// draw the button!
				m_ilButtons.Draw(&dc, iButton, p, ILD_TRANSPARENT);

			} else if (m_bUseDrawState) {
				// use DrawState to draw disabled button: must convert to icon
				HICON hIcon=m_ilButtons.ExtractIcon(iButton);
				ASSERT(hIcon);
				dc.DrawState(p, CSize(0,0), hIcon, DSS_DISABLED, (HBRUSH)NULL);
				DestroyIcon(hIcon);

			} else
				// use DrawEmbossed to draw disabeld button, w/color flag
				PLDrawEmbossed(dc, m_ilButtons, iButton, p,
					m_bDrawDisabledButtonsInColor);

		} else {
			// no button: look for custom checked/unchecked bitmaps
			CMenuItemInfo info;
			info.fMask = MIIM_CHECKMARKS;
			GetMenuItemInfo((HMENU)lpds->hwndItem,
				lpds->itemID, MF_BYCOMMAND, &info);
			if (bChecked || info.hbmpUnchecked) {
				bHaveButn = Draw3DCheckmark(dc, rcButn, bSelected,
					bChecked ? info.hbmpChecked : info.hbmpUnchecked);
			}
		}

		// Done with button, now paint text. First do background if needed.
		int cxButn = m_szButton.cx;				// width of button
		COLORREF colorBG = GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
		if (bSelected || lpds->itemAction==ODA_SELECT) {
			// selected or selection state changed: paint text background
			CRect rcBG = rcItem;							// whole rectangle
			if (bHaveButn)									// if there's a button:
				rcBG.left += cxButn + CXGAP;			//  don't paint over it!
			PLFillRect(dc, rcBG, colorBG);	// paint it!
		}

		// 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)) {
			// 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('\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
	if (!hbmCheck) {
		CBitmap 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, SRCCOPY);
	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);

		// 12 Nov 1998	- Wang Jun - Fixes debug assert in system menu.
		// Check if click system menu.
		bSysMenu = TRUE;
		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
		}
	}
}

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

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

⌨️ 快捷键说明

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