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

📄 bcgpopupmenu.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This source code is a part of BCGControlBar library.
// You may use, compile or redistribute it as part of your application 
// for free. You cannot redistribute it as a part of a software development 
// library without the agreement of the author. If the sources are 
// distributed along with the application, you should leave the original 
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES on your own risk.
// 
// Stas Levin <stas@iet.co.il>
//*******************************************************************************

// BCGPopupMenu.cpp : implementation file
//

#include "stdafx.h"

#include "BCGPopupMenu.h"
#include "BCGMenuBar.h"
#include "globals.h"
#include "BCGToolbarMenuButton.h"
#include "BCGMDIFrameWnd.h"
#include "BCGFrameWnd.h"
#include "BCGOleIPFrameWnd.h"
#include "BCGMenuBar.h"
#include "menupage.h"
#include "MenuHash.h"
#include "MenuImages.h"
#include "BCGShowAllButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static COLORREF PixelAlpha (COLORREF srcPixel, int percent);
inline static void SetAlphaPixel (COLORREF* pBits, CRect rect, int x, int y, int percent, int iShadowSize);

/////////////////////////////////////////////////////////////////////////////
// CBCGPopupMenu

static const int iBorderSize = 2;
static const int iAnimTimerId = 1;
static const int iAnimTimerDuration = 30;
static const int iScrollTimerId = 2;
static const int iScrollTimerDuration = 80;
static const int iShadowSize = 7;

CString	CBCGPopupMenu::m_strClassName;
int	CBCGPopupMenu::m_nBitsPerPixel = 0;
CBCGPopupMenu::ANIMATION_TYPE CBCGPopupMenu::m_AnimationType = NO_ANIMATION;

IMPLEMENT_SERIAL(CBCGPopupMenu, CMiniFrameWnd, VERSIONABLE_SCHEMA | 1)

CBCGPopupMenu::CBCGPopupMenu() :
	m_pMenuCustomizationPage (NULL)
{
	Initialize ();
}
//****************************************************************************************
CBCGPopupMenu::CBCGPopupMenu(CBCGMenuPage* pCustPage, LPCTSTR lpszTitle) :
	m_pMenuCustomizationPage (pCustPage),
	m_strCaption (lpszTitle)
{
	Initialize ();
}
//****************************************************************************************
void CBCGPopupMenu::Initialize ()
{
	m_hMenu = NULL;
	m_ptLocation = CPoint (0, 0);
	m_ptLocationAnim = CPoint (-1, -1);
	m_pParentBtn = NULL;
	m_bAutoDestroyParent = TRUE;
	m_bAutoDestroy = TRUE;
	m_FinalSize = CSize (0, 0);
	m_AnimSize = CSize (0, 0);
	m_bAnimationIsDone = (m_AnimationType == NO_ANIMATION);
	m_bScrollable = FALSE;
	m_bTobeDstroyed = FALSE;
	m_bShown = FALSE;

	m_iMaxWidth = -1;

	m_rectScrollUp.SetRectEmpty ();
	m_rectScrollDn.SetRectEmpty ();

	m_iScrollMode = 0;

	m_bIsAnimRight = TRUE;
	m_bIsAnimDown = TRUE;

	m_bSaveShadows = FALSE;

	if (m_nBitsPerPixel == 0)	// Not defined yet
	{
		CClientDC dc (NULL);
		m_nBitsPerPixel = dc.GetDeviceCaps (BITSPIXEL);
	}

	m_iShadowSize = CBCGMenuBar::IsMenuShadows () &&
					!CBCGToolBar::IsCustomizeMode () &&
					m_nBitsPerPixel > 8 ? // Don't draw shadows in 256 colors or less
						iShadowSize : 0;
}
//****************************************************************************************
CBCGPopupMenu::~CBCGPopupMenu()
{
	if (m_bAutoDestroy && m_hMenu != NULL)
	{
		::DestroyMenu (m_hMenu);
	}
}

BEGIN_MESSAGE_MAP(CBCGPopupMenu, CMiniFrameWnd)
	//{{AFX_MSG_MAP(CBCGPopupMenu)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_MOUSEACTIVATE()
	ON_WM_DESTROY()
	ON_WM_KEYDOWN()
	ON_WM_ERASEBKGND()
	ON_WM_ACTIVATEAPP()
	ON_WM_TIMER()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBCGPopupMenu message handlers

BOOL CBCGPopupMenu::Create (CWnd* pWndParent, int x, int y, HMENU hMenu, BOOL bLocked)
{
	// Play standard menu popup sound!
	::PlaySound (_T("MenuPopup"), NULL, SND_ASYNC | SND_NODEFAULT);

	ASSERT (pWndParent != NULL);

	if (m_strClassName.IsEmpty ())
	{
		m_strClassName = ::AfxRegisterWndClass (
			CS_SAVEBITS,
			::LoadCursor(NULL, IDC_ARROW),
			(HBRUSH)(COLOR_BTNFACE + 1), NULL);
	}

	m_hMenu = hMenu;

	if (x == -1 && y == -1)	// Undefined position
	{
		if (pWndParent != NULL)
		{
			CRect rectParent;
			pWndParent->GetClientRect (&rectParent);
			pWndParent->ClientToScreen (&rectParent);

			m_ptLocation = CPoint (rectParent.left + 5, rectParent.top + 5);
		}
		else
		{
			m_ptLocation = CPoint (0, 0);
		}
	}
	else
	{
		m_ptLocation = CPoint (x, y);
	}

	DWORD dwStyle = WS_POPUP;
	if (m_pMenuCustomizationPage != NULL)
	{
		dwStyle |= (WS_CAPTION | WS_SYSMENU);
	}

	BOOL bIsAnimate = (m_AnimationType != NO_ANIMATION) && 
					!CBCGToolBar::IsCustomizeMode ();

	CRect rect (x, y, x, y);
	BOOL bCreated = CMiniFrameWnd::CreateEx (
				0,
				m_strClassName, m_strCaption,
				dwStyle, rect,
				pWndParent->GetOwner () == NULL ? 
					pWndParent : pWndParent->GetOwner ());
	if (!bCreated)
	{
		return FALSE;
	}

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

	pMenuBar->m_bLocked = bLocked;

	if (bIsAnimate)
	{
		if (m_bIsAnimDown)
		{
			pMenuBar->SetOffset (pMenuBar->m_Buttons.GetCount () - 1);
		}

		//--------------------------
		// Adjust initial menu size:
		//--------------------------
		m_AnimSize = m_FinalSize;
		m_AnimSize.cy = pMenuBar->GetRowHeight ();

		if (m_AnimationType == UNFOLD)
		{
			m_AnimSize.cx = pMenuBar->GetColumnWidth ();
		}

		//------------------------------
		// Adjust initial menu position:
		//------------------------------
		m_ptLocationAnim = m_ptLocation;

		if (!m_bIsAnimRight)
		{
			m_ptLocationAnim.x += m_FinalSize.cx - m_AnimSize.cx;
		}

		if (!m_bIsAnimDown)
		{
			m_ptLocationAnim.y += m_FinalSize.cy - m_AnimSize.cy;
		}

		SetWindowPos (NULL, m_ptLocationAnim.x, m_ptLocationAnim.y, 
					m_AnimSize.cx, m_AnimSize.cy,
					SWP_NOZORDER | SWP_NOACTIVATE);

		SetTimer (iAnimTimerId, iAnimTimerDuration, NULL);
	}

	//--------------------------------------
	// Update windows covered by the shadow:
	//--------------------------------------
	UpdateBottomWindows (!m_bAnimationIsDone);

	ShowWindow (SW_SHOWNOACTIVATE);

	if (CBCGToolBar::IsCustomizeMode ())
	{
		pMenuBar->Invalidate ();
		pMenuBar->UpdateWindow ();
	}

	return TRUE;
}
//****************************************************************************************

//-----------------------------------------------------
// My "classic " trick - how I can access to protected
// member m_pRecentFileList?
//-----------------------------------------------------
class CBCGApp : public CWinApp
{
	friend class CBCGPopupMenu;
};

int CBCGPopupMenu::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CMiniFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!m_wndMenuBar.Create (this, dwDefaultToolbarStyle | CBRS_TOOLTIPS | CBRS_FLYBY))
	{
		TRACE(_T("Can't create popup menu bar\n"));
		return FALSE;
	}

	CBCGPopupMenu* pParentPopupMenu = GetParentPopupMenu ();
	if (pParentPopupMenu != NULL)
	{
		m_iMaxWidth = pParentPopupMenu->m_iMaxWidth;
	}

	m_wndMenuBar.m_iMaxWidth = m_iMaxWidth;
	m_wndMenuBar.SetOwner (GetParent ());

	return InitMenuBar () ? 0 : 1;
}
//****************************************************************************************
void CBCGPopupMenu::OnSize(UINT nType, int cx, int cy) 
{
	CMiniFrameWnd::OnSize(nType, cx, cy);
	
	CBCGPopupMenuBar* pMenuBar = GetMenuBar ();
	ASSERT_VALID (pMenuBar);

	if (pMenuBar->GetSafeHwnd () == NULL)
	{
		return;
	}

	CRect rectClient;
	GetClientRect (rectClient);

	if (m_bAnimationIsDone && !CBCGToolBar::IsCustomizeMode ())
	{
		rectClient.right -= m_iShadowSize;
		rectClient.bottom -= m_iShadowSize;
	}

	rectClient.DeflateRect (iBorderSize, iBorderSize);

	if (m_bScrollable)
	{
		int iScrollBtnHeight = CMenuImages::Size ().cy + 2 * iBorderSize;

		pMenuBar->SetWindowPos (NULL, rectClient.left, 
					rectClient.top + iScrollBtnHeight + iBorderSize,
					rectClient.Width (), 
					rectClient.Height () - 2 * iScrollBtnHeight - iBorderSize,
					SWP_NOZORDER | SWP_NOACTIVATE);
		
		m_rectScrollUp = rectClient;
		m_rectScrollUp.top += iBorderSize;
		m_rectScrollUp.bottom = m_rectScrollUp.top + iScrollBtnHeight;

		m_rectScrollDn = rectClient;
		m_rectScrollDn.top = m_rectScrollDn.bottom - iScrollBtnHeight;
	}
	else
	{
		UINT uiFlags = SWP_NOZORDER | SWP_NOACTIVATE;
		if (!m_bAnimationIsDone)
		{
			uiFlags |= SWP_NOREDRAW;
		}

		pMenuBar->SetWindowPos (NULL, rectClient.left, rectClient.top,
					rectClient.Width (), 
					rectClient.Height (),
					uiFlags);

		m_rectScrollUp.SetRectEmpty ();
		m_rectScrollDn.SetRectEmpty ();
	}
}
//****************************************************************************************
void CBCGPopupMenu::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	CRect rectClient;	// Client area rectangle
	GetClientRect (&rectClient);

	BOOL bDrawShadows = m_iShadowSize != 0 &&
						m_bAnimationIsDone && 
						!CBCGToolBar::IsCustomizeMode ();

	if (bDrawShadows)
	{
		rectClient.right -= m_iShadowSize;
		rectClient.bottom -= m_iShadowSize;
	}

	if (bDrawShadows)
	{
		DrawShadows (dc, rectClient);
	}

	dc.Draw3dRect (rectClient,
					globalData.clrBtnLight, 
					globalData.clrBtnDkShadow);
	rectClient.DeflateRect (1, 1);
	dc.Draw3dRect (rectClient,
					globalData.clrBtnHilite,
					globalData.clrBtnShadow);

	if (m_bScrollable)
	{
		DrawImage (&dc, m_rectScrollUp, 
			IsScrollUpAvailable () ? CMenuImages::IdArowUp : CMenuImages::IdArowUpDisabled, 
					m_iScrollMode < 0);
		DrawImage (&dc, m_rectScrollDn, 
					IsScrollDnAvailable () ? CMenuImages::IdArowDown : CMenuImages::IdArowDownDsbl,
					m_iScrollMode > 0);
	}

	m_bShown = TRUE;
}
//****************************************************************************************
int CBCGPopupMenu::OnMouseActivate(CWnd* /*pDesktopWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
{
	return MA_NOACTIVATE;
}
//****************************************************************************************
void CBCGPopupMenu::RecalcLayout (BOOL /*bNotify*/) 
{
#ifdef _DEBUG
	if (m_pParentBtn != NULL)
	{
		ASSERT_VALID (m_pParentBtn);
		ASSERT (m_pParentBtn->m_pPopupMenu == this);
	}
#endif // _DEBUG

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

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

	CRect rectScreen;
	::SystemParametersInfo (SPI_GETWORKAREA, 0, &rectScreen, 0);

	CSize size = pMenuBar->CalcSize ();
	size.cx += iBorderSize * 2;
	size.cy += iBorderSize * 2;

	if (m_pMenuCustomizationPage != NULL)
	{
		size.cy += ::GetSystemMetrics (SM_CYSMCAPTION);
		size.cy += 2 * ::GetSystemMetrics (SM_CYBORDER) + 5;
	}

	//---------------------------------------------
	// Adjust the menu position by the screen size:
	//---------------------------------------------
	if (m_ptLocation.x + size.cx > rectScreen.right)
	{
		//-----------------------------------------------------
		// Menu can't be overlapped with the parent popup menu!
		//-----------------------------------------------------
		CBCGPopupMenu* pParentMenu = GetParentPopupMenu ();
		CBCGMenuBar* pParentMenuBar = m_pParentBtn == NULL ? NULL :
			DYNAMIC_DOWNCAST (CBCGMenuBar, m_pParentBtn->m_pWndParent);

		if (pParentMenu != NULL)
		{
			CRect rectParent;
			pParentMenu->GetWindowRect (rectParent);

			m_ptLocation.x = rectParent.left - size.cx;

⌨️ 快捷键说明

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