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

📄 coolmenu.cpp

📁 一个很好的富文本编辑程序,类似于windows中的写字板但并不同
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				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
				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
				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);
		}
	}
}

//////////////////
// 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(_T('&'));
			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;
		}
	}
	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);
		}
	}
}

// fix for virtual key names - Seain Conover (1999/01/09) 

CString CCoolMenuManager::GetVirtualKeyName( const CString strVirtKey ) const
{
	CString strResult;
	
	if		( strVirtKey == _T("Num 7"))		{ strResult = _T("Home"); }
	else if ( strVirtKey == _T("Num 1"))		{ strResult = _T("End");  }
	else if ( strVirtKey == _T("Num 9"))		{ strResult = _T("PgUp"); }
	else if ( strVirtKey == _T("Num 3"))		{ strResult = _T("PgDn"); }
	else if ( strVirtKey == _T("Num 0"))		{ strResult = _T("Ins");  }
	else if ( strVirtKey == _T("Num Del"))		{ strResult = _T("Del");  }
	else
	{
		strResult = strVirtKey;
	}
	
	return strResult;
}

//////////////////
// 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('\t'));
	if (iTabPos > 0)
		sItemName = sItemName.Left(iTabPos);
*/
	BOOL bFound = FALSE;/*
	for (ACCEL* pa = GetAccel(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));
			// Seain Conover (1999/01/09) 
			sItemName += GetVirtualKeyName( 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;
}

// Peter Tewkesbury
BOOL CCoolMenuManager::AddSingleBitmap(UINT nBitmapID, UINT n, UINT *nID)
{
	// load bitmap
	HBITMAP hbmBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
		MAKEINTRESOURCE(nBitmapID), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
	ASSERT(hbmBitmap);

	if (!hbmBitmap) {
		TRACE(_T("*** Can't load bitmap %d!\n"), nBitmapID);
		return FALSE;
	}

	// Assign Bitmap to CBitmap
	CBitmap bmBitmap;
	bmBitmap.Attach(hbmBitmap); // destructor will detach & destroy
	
	// OK, I have the bitmap - Check that Bitmaps are correct size.
	if (m_szBitmap.cx==0) 
	{
		// First toolbar: initialized bitmap/button sizes and create image list.
		CSize sz(16,15);
		m_szBitmap = sz;
		m_szButton = sz + CSize(CXBUTTONMARGIN<<1, CYBUTTONMARGIN<<1);
		VERIFY(m_ilButtons.Create(sz.cx, sz.cy, ILC_MASK, 0, 10));
		
	} 
	
	// Add Bitmap to ImageList
	int iNextImage = m_ilButtons.GetImageCount();
	m_ilButtons.Add(&bmBitmap, GetSysColor(COLOR_3DFACE)); 
	
	// Add ID to Map.
	for(UINT i=0;i<n;i++)
	{
		if (nID[i] > 0) 
		{
			if (GetButtonIndex(nID[i]) >= 0) 
			{
				TRACE(_T("*** Duplicate button ID %d ignored\n"), nID[i]);
			} 
			else m_mapIDtoImage.SetAt(nID[i], (void*)iNextImage++); 
		}
	}
	
	// All Done.
	return TRUE;
}

////////////////////////////////////////////////////////////////
// Helper functions

//////////////////
// Load a bitmap, converting the standard colors.
// Calls AfxLoadSysColorBitmap to do the work.
//
// RGB(0x00, 0x00, 0x00) (black)      --> COLOR_BTNTEXT
// RGB(0x80, 0x80, 0x80) (dark gray)  --> COLOR_3DSHADOW
// RGB(0xC0, 0xC0, 0xC0) (gray)       --> COLOR_3DFACE
// RGB(0xFF, 0xFF, 0xFF) (white)      --> COLOR_3DHILIGHT
// 
HBITMAP PLLoadSysColorBitmap(LPCTSTR lpResName, BOOL bMono)
{
	HINSTANCE hInst = AfxFindResourceHandle(lpResName, RT_BITMAP);
	HRSRC hRsrc = ::FindResource(hInst, lpResName, RT_BITMAP);
	if (hRsrc == NULL)
		return NULL;
	return AfxLoadSysColorBitmap(hInst, hRsrc, bMono);
}

//////////////////
// Shorthand to fill a rectangle with a solid color.
//
void PLFillRect(CDC& dc, const CRect& rc, COLORREF color)
{
	CBrush brush(color);
	CBrush* pOldBrush = dc.SelectObject(&brush);
	dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
	dc.SelectObject(pOldBrush);
}

// This is the magic ROP code used to generate the embossed look for
// a disabled button. It's listed in Appendix F of the Win32 Programmer's
// Reference as PSDPxax (!) which is a cryptic reverse-polish notation for
//
// ((Destination XOR Pattern) AND Source) XOR Pattern
//
// which I leave to you to figure out. In the case where I apply it,
// Source is a monochrome bitmap which I want to draw in such a way that
// the black pixels get transformed to the brush color and the white pixels
// draw transparently--i.e. leave the Destination alone.
//
// black ==> Pattern (brush)
// white ==> Destintation (ie, transparent)
//
// 0xb8074a is the ROP code that does this. For more info, see Charles
// Petzold, _Programming Windows_, 2nd Edition, p 622-624.
//
#define TRANSPARENTROP 0xb8074a

//////////////////
// Draw an image with the embossed (disabled) look.
//
//		dc			device context to draw in
//		il			image list containing image
//		i			index of image to draw
//		p			point in dc to draw image at
//    bColor	do color embossing. Default is B/W.
//
void PLDrawEmbossed(CDC& dc, CImageList& il, int i,
	CPoint p, BOOL bColor)
{
	IMAGEINFO info;
	VERIFY(il.GetImageInfo(0, &info));
	CRect rc = info.rcImage;
	int cx = rc.Width();
	int cy = rc.Height();

	// create memory dc
	CDC memdc;
	memdc.CreateCompatibleDC(&dc);

	// create mono or color bitmap
	CBitmap bm;
	if (bColor)
		bm.CreateCompatibleBitmap(&dc, cx, cy);
	else
		bm.CreateBitmap(cx, cy, 1, 1, NULL);

	// draw image into memory DC--fill BG white first
	CBitmap* pOldBitmap = memdc.SelectObject(&bm);
	memdc.PatBlt(0, 0, cx, cy, WHITENESS);
	il.Draw(&memdc, i, CPoint(0,0), ILD_TRANSPARENT);

	// This seems to be required. Why, I don't know. ???
	COLORREF colorOldBG = dc.SetBkColor(RGB(255,255,255)); // white

	// Draw using hilite offset by (1,1), then shadow
	CBrush brShadow(GetSysColor(COLOR_3DSHADOW));
	CBrush brHilite(GetSysColor(COLOR_3DHIGHLIGHT));
	CBrush* pOldBrush = dc.SelectObject(&brHilite);
	dc.BitBlt(p.x+1, p.y+1, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
	dc.SelectObject(&brShadow);
	dc.BitBlt(p.x, p.y, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
	dc.SelectObject(pOldBrush);
	dc.SetBkColor(colorOldBG);				 // restore
	memdc.SelectObject(pOldBitmap);		 // ...
}

⌨️ 快捷键说明

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