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

📄 bcgpopupmenu.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//**************************************************************************************
void CBCGPopupMenu::SetMaxWidth (int iMaxWidth)
{
	if (iMaxWidth == m_iMaxWidth)
	{
		return;
	}

	m_iMaxWidth = iMaxWidth;
	if (GetSafeHwnd () == NULL)
	{
		return;
	}

	CBCGPopupMenuBar* pMenuBar = GetMenuBar ();
	ASSERT_VALID (pMenuBar);

	if (!::IsWindow (m_hWnd) ||
		!::IsWindow (pMenuBar->m_hWnd))
	{
		return;
	}

	pMenuBar->m_iMaxWidth = m_iMaxWidth;
	RecalcLayout ();
}
//*************************************************************************************
BOOL CBCGPopupMenu::InitMenuBar ()
{
	if (m_hMenu != NULL)
	{
		if (m_pParentBtn != NULL || 
			!g_menuHash.LoadMenuBar (m_hMenu, &m_wndMenuBar))
		{
			//-------------------------------------------
			// Failed to restore, load the default state:
			//-------------------------------------------
			if (!m_wndMenuBar.ImportFromMenu (m_hMenu, !HideRarelyUsedCommands ()))
			{
				TRACE(_T("Can't import menu\n"));
				return FALSE;
			}
		}
	}

	//----------------------------------------
	// Maybe, we should process the MRU files:
	//----------------------------------------
	CRecentFileList* pMRUFiles = 
		((CBCGApp*) AfxGetApp ())->m_pRecentFileList;

	if (pMRUFiles != NULL && !CBCGToolBar::IsCustomizeMode ())
	{
		int iMRUItemIndex = 0;
		BOOL bIsPrevSeparator = FALSE;

		for (POSITION pos = m_wndMenuBar.m_Buttons.GetHeadPosition (); 
			pos != NULL; iMRUItemIndex ++)
		{
			POSITION posSave = pos;

			CBCGToolbarButton* pButton = 
				(CBCGToolbarButton*) m_wndMenuBar.m_Buttons.GetNext (pos);
			ASSERT (pButton != NULL);

			if (pButton->m_nID == ID_FILE_MRU_FILE1 &&
				pButton->m_strText == _T("Recent File"))
			{
				//------------------------------
				// Remove dummy item ("Recent"):
				//------------------------------
				m_wndMenuBar.m_Buttons.RemoveAt (posSave);
				delete pButton;

				TCHAR szCurDir [_MAX_PATH];
				::GetCurrentDirectory (_MAX_PATH, szCurDir);

				int nCurDir = lstrlen (szCurDir);
				ASSERT (nCurDir >= 0);

				szCurDir [nCurDir] = _T('\\');
				szCurDir [++ nCurDir] = _T('\0');

				//---------------
				// Add MRU files:
				//---------------
				int iNumOfFiles = 0;	// Actual added to menu
				for (int i = 0; i < pMRUFiles->GetSize (); i ++)
				{
					CString strName;

					if (pMRUFiles->GetDisplayName (strName, i, 
						szCurDir, nCurDir))
					{
						//---------------------
						// Add shortcut number:
						//---------------------
						CString strItem;
						strItem.Format (_T("&%d %s"), ++iNumOfFiles, strName);

						m_wndMenuBar.InsertButton (
							CBCGToolbarMenuButton (
								ID_FILE_MRU_FILE1 + i, NULL,
								-1, strItem),
							iMRUItemIndex ++);
					}
				}

				//------------------------------------------------------
				// Usualy, the MRU group is "covered" by two seperators.
				// If MRU list is empty, remove redandant separator:
				//------------------------------------------------------
				if (iNumOfFiles == 0 &&	// No files were added
					bIsPrevSeparator &&	// Prev. button was separator
					pos != NULL)		// Not a last button
				{
					posSave = pos;

					pButton = (CBCGToolbarButton*) 
						m_wndMenuBar.m_Buttons.GetNext (pos);
					ASSERT (pButton != NULL);

					if (pButton->m_nStyle & TBBS_SEPARATOR)
					{
						//---------------------------------------
						// Next button also separator, remove it:
						//---------------------------------------
						m_wndMenuBar.m_Buttons.RemoveAt (posSave);
						delete pButton;
					}
				}

				break;
			}

			bIsPrevSeparator = (pButton->m_nStyle & TBBS_SEPARATOR);
		}
	}

	//-----------------------------------------------------------------------------
	// Maybe, main application frame should update the popup menu context before it
	// displayed (example - windows list):
	//-----------------------------------------------------------------------------
	if (!ActivatePopupMenu (GetTopLevelFrame (), this))
	{
		return FALSE;
	}

	RecalcLayout ();
	return TRUE;
}
//************************************************************************************
BOOL CBCGPopupMenu::HideRarelyUsedCommands () const
{
	return (m_pParentBtn != NULL &&
			m_pParentBtn->GetParentWnd ()->IsKindOf (RUNTIME_CLASS (CBCGMenuBar)));
}
//************************************************************************************
void CBCGPopupMenu::UpdateBottomWindows (BOOL bCheckOnly)
{
	if (m_iShadowSize > 0)
	{
		CWnd* pWndMain = GetTopLevelParent ();
		if (pWndMain != NULL)
		{
			//---------------------------------------------------------
			// If menu will be shown outside of the application window,
			// don't show shadows!
			//---------------------------------------------------------
			CRect rectMain;
			pWndMain->GetWindowRect (rectMain);

			CRect rectMenu (m_ptLocation, 
				CSize (m_FinalSize.cx + m_iShadowSize, m_FinalSize.cy + m_iShadowSize));

			CRect rectInter;
			rectInter.UnionRect (&rectMenu, &rectMain);

			if (rectInter != rectMain)
			{
				m_iShadowSize = 0;

				if (!bCheckOnly)
				{
					SetWindowPos (NULL, -1, -1, m_FinalSize.cx, m_FinalSize.cy,
								SWP_NOMOVE | SWP_NOZORDER |
								SWP_NOACTIVATE);
				}
			}
			else
			{
				pWndMain->UpdateWindow ();
			}
		}
	}
}

// ==================================================================
// 
// FUNCTION :  DrawShadows ()
// 
// * Description : Draws the shadow for a rectangular screen element
// 
// * Authors: [Stas Levin ]
//			  [Timo Hummel], Modified: [8/11/99 5:06:59 PM]
//			  
// * Function parameters : 
// [dc] -		The device context to draw into
// [rect] -		The CRect of the rectangular region to draw the
//			    shadow around (altough the CDC needs to be big enough
//				to hold the shadow)
// ==================================================================
void CBCGPopupMenu::DrawShadows (CDC& dc, const CRect& rect)
{
	const int iMinBrightness = 100;
	const int iMaxBrightness = 50;

	if (m_iShadowSize == 0)
	{
		return;
	}

	int cx = rect.Width ();
	int cy = rect.Height ();

	if (m_bmpShadowRight.GetSafeHandle () != NULL &&
		m_bmpShadowBottom.GetSafeHandle () != NULL)
	{
		//---------------------------------------------------
		// Shadows are already implemented, put them directly
		// to the DC:
		//---------------------------------------------------
		dc.DrawState (CPoint (rect.right + 1, rect.top), 
					CSize (m_iShadowSize, cy + m_iShadowSize),
					&m_bmpShadowRight, DSS_NORMAL);

		dc.DrawState (CPoint (rect.left, rect.bottom + 1),
					CSize (cx + m_iShadowSize, m_iShadowSize),
					&m_bmpShadowBottom, DSS_NORMAL);
		return;
	}

	ASSERT (m_bmpShadowRight.GetSafeHandle () == NULL);
	ASSERT (m_bmpShadowBottom.GetSafeHandle () == NULL);

	//--------------------------------------------
	// Copy screen content into the memory bitmap:
	//--------------------------------------------
	CDC dcMem;
	if (!dcMem.CreateCompatibleDC (&dc))
	{
		return;
	}

	//--------------------------------------------
	// Gets the whole menu and changes the shadow.
	//--------------------------------------------
	CBitmap	bmpMem;
	if (!bmpMem.CreateCompatibleBitmap (&dc, cx + m_iShadowSize, cy + m_iShadowSize))
	{
		return;
	}

	CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);
	ASSERT (pOldBmp != NULL);

	LPBITMAPINFO lpbi;

		// Fill in the BITMAPINFOHEADER
	lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) ];
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	lpbi->bmiHeader.biWidth = cx + m_iShadowSize;
	lpbi->bmiHeader.biHeight = cy + m_iShadowSize;
	lpbi->bmiHeader.biPlanes = 1;
	lpbi->bmiHeader.biBitCount = 32;
	lpbi->bmiHeader.biCompression = BI_RGB;
	lpbi->bmiHeader.biSizeImage = (cx + m_iShadowSize) * (cy + m_iShadowSize);
	lpbi->bmiHeader.biXPelsPerMeter = 0;
	lpbi->bmiHeader.biYPelsPerMeter = 0;
	lpbi->bmiHeader.biClrUsed = 0;
	lpbi->bmiHeader.biClrImportant = 0;

	COLORREF* pBits = NULL;
	HBITMAP hmbpDib = CreateDIBSection (
		dcMem.m_hDC, lpbi, DIB_RGB_COLORS, (void **)&pBits,
		NULL, NULL);

	if (hmbpDib == NULL || pBits == NULL)
	{
		delete lpbi;
		return;
	}

	dcMem.SelectObject (hmbpDib);
	dcMem.BitBlt (0, 0, cx + m_iShadowSize, cy + m_iShadowSize, &dc, rect.left, rect.top, SRCCOPY);

	//----------------------------------------------------------------------------
	// Process shadowing:
	// For having a very nice shadow effect, its actually hard work. Currently,
	// I'm using a more or less "hardcoded" way to set the shadows (by using a
	// hardcoded algorythm):
	//
	// This algorythm works as follows:
	// 
	// It always draws a few lines, from left to bottom, from bottom to right,
	// from right to up, and from up to left). It does this for the specified
	// shadow width and the color settings.
	//-----------------------------------------------------------------------------

	// For speeding up things, iShadowOffset is the
	// value which is needed to multiply for each shadow step
	int iShadowOffset = (iMaxBrightness - iMinBrightness) / m_iShadowSize;

	// Loop for drawing the shadow
	// Actually, this was simpler to implement than I thought
	for (int c = 0; c < m_iShadowSize; c++)
	{
		// Draw the shadow from left to bottom
		for (int y = cy; y < cy + (m_iShadowSize - c); y++)
		{
			SetAlphaPixel (pBits, rect, c + m_iShadowSize, y, 
				iMaxBrightness - ((m_iShadowSize  - c) * (iShadowOffset)),m_iShadowSize);
		}

		// Draw the shadow from left to right
		for (int x = m_iShadowSize + (m_iShadowSize - c); x < cx + c; x++)
		{
			SetAlphaPixel(pBits, rect,x, cy + c,
				iMaxBrightness - ((c) * (iShadowOffset)),m_iShadowSize);
		}

		// Draw the shadow from top to bottom
		for (int y1 = m_iShadowSize + (m_iShadowSize - c); y1 < cy + c + 1; y1++)
		{
			SetAlphaPixel(pBits, rect, cx+c, y1, 
				iMaxBrightness - ((c) * (iShadowOffset)),
				m_iShadowSize);
		}
		
		// Draw the shadow from top to left
		for (int x1 = cx; x1 < cx + (m_iShadowSize - c); x1++)
		{
			SetAlphaPixel (pBits, rect, x1, c + m_iShadowSize,
				iMaxBrightness - ((m_iShadowSize - c) * (iShadowOffset)),
				m_iShadowSize);
		}
	}

	//-----------------------------------------
	// Copy shadowed bitmap back to the screen:
	//-----------------------------------------
	dc.BitBlt (rect.left, rect.top, cx + m_iShadowSize, cy + m_iShadowSize, 
				&dcMem, 0, 0, SRCCOPY);

	if (m_bSaveShadows)
	{
		//------------------------------------
		// Save shadows in the memory bitmaps:
		//------------------------------------
		m_bmpShadowRight.CreateCompatibleBitmap (&dc, m_iShadowSize, cy + m_iShadowSize);
		
		dcMem.SelectObject (&m_bmpShadowRight);
		dcMem.BitBlt (0, 0, m_iShadowSize, cy + m_iShadowSize,
						&dc, rect.right + 1, rect.top, SRCCOPY);

		m_bmpShadowBottom.CreateCompatibleBitmap (&dc, cx + m_iShadowSize, m_iShadowSize);

		dcMem.SelectObject (&m_bmpShadowBottom);
		dcMem.BitBlt (0, 0, cx + m_iShadowSize, m_iShadowSize,
						&dc, rect.left, rect.bottom + 1, SRCCOPY);
	}

	dcMem.SelectObject (pOldBmp);
	DeleteObject (hmbpDib);
	delete lpbi;
}

// ==================================================================
// 
// FUNCTION :  static void SetAlphaPixel ()
// 
// * Description : Draws an alpha blended pixel
// 
// * Author : [Timo Hummel], Created : [8/11/99 5:04:38 PM]
// 
// * Function parameters : 
// [pBits] -	The DIB bits
// [x] -		X-Coordinate
// [y] -		Y-Coordinate
// [percent] -	Percentage to blit (100 = hollow, 0 = solid)
// 
// ==================================================================
inline static void SetAlphaPixel (COLORREF* pBits, CRect rect, int x, int y, int percent, int m_iShadowSize)
{
	// Our direct bitmap access swapped the y coordinate...
	y = (rect.Height()+m_iShadowSize)- y;

	COLORREF* pColor = (COLORREF*) (pBits + (rect.Width () + m_iShadowSize) * y + x);
	*pColor = PixelAlpha (*pColor, percent);
}

// ==================================================================
// 
// FUNCTION :  PixelAlpha ()
// 
// * Description : Shades a color value with a specified percentage
// 
// * Author : [Timo Hummel], Created : [8/11/99 2:37:04 PM]
// 
// * Returns : [COLORREF] - The result pixel
// 
// * Function parameters : 
// [srcPixel] - The source pixel
// [percent] -  Percentage (amount of shadow)
//
// Example: percent = 10    makes the pixel around 10 times darker
//          percent = 50    makes the pixel around 2 times darker
// 
// ==================================================================
COLORREF PixelAlpha (COLORREF srcPixel, int percent)
{
	// My formula for calculating the transpareny is as
	// follows (for each single color):
	//
	//							   percent
	// destPixel = sourcePixel * ( ------- )
	//                               100
	//
	// This is not real alpha blending, as it only modifies the brightness,
	// but not the color (a real alpha blending had to mix the source and
	// destination pixels, e.g. mixing green and red makes yellow).
	// For our nice "menu" shadows its good enough.

	COLORREF clrFinal = RGB ( (GetRValue (srcPixel) * percent) / 100, 
							  (GetGValue (srcPixel) * percent) / 100, 
							  (GetBValue (srcPixel) * percent) / 100);

	return (clrFinal);

}

⌨️ 快捷键说明

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