www.pudn.com > editpad_src > bcgpopupmenu.cpp, change:1999-11-30,size:48707b


//******************************************************************************* 
// 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; 
		} 
		else if (pParentMenuBar != NULL &&  
			(pParentMenuBar->m_dwStyle & CBRS_ORIENT_HORZ) == 0) 
		{ 
			//------------------------------------------------ 
			// Parent menu bar is docked vertical, place menu  
			// in the left or right side of the parent frame: 
			//------------------------------------------------ 
			CRect rectParent; 
			pParentMenuBar->GetWindowRect (rectParent); 
 
			m_ptLocation.x = rectParent.left - size.cx; 
		} 
		else 
		{ 
			m_ptLocation.x = rectScreen.right - size.cx - 1; 
		} 
 
		if (m_ptLocation.x  rectScreen.left) 
		{ 
			m_ptLocation.x = rectScreen.left; 
		} 
 
		if (m_AnimationType == UNFOLD) 
		{ 
			m_bIsAnimRight = FALSE; 
		} 
	} 
 
	if (m_ptLocation.y + size.cy > rectScreen.bottom) 
	{ 
		if (m_bScrollable) 
		{ 
			size.cy = rectScreen.bottom - m_ptLocation.y; 
		} 
		else 
		{ 
			if (m_pParentBtn != NULL && m_pParentBtn->GetParentWnd () != NULL) 
			{ 
				CPoint ptRight (m_pParentBtn->Rect ().right, 0); 
                m_pParentBtn->GetParentWnd ()->ClientToScreen (&ptRight); 
 
                CPoint ptTop (0, m_pParentBtn->Rect ().top - size.cy); 
				m_pParentBtn->GetParentWnd ()->ClientToScreen (&ptTop); 
 
                if (ptTop.y  0) 
                { 
                    m_ptLocation.y = 0; 
                    m_ptLocation.x = ptRight.x; 
                } 
                else 
                { 
                    m_ptLocation.y = ptTop.y; 
                } 
			} 
			else 
			{ 
				m_ptLocation.y -= size.cy; 
			} 
 
			if (m_ptLocation.y  rectScreen.top) 
			{ 
				m_ptLocation.y = rectScreen.top; 
			} 
		} 
 
		if (m_ptLocation.y + size.cy > rectScreen.bottom) 
		{ 
			EnableScrolling (); 
		} 
 
		m_bIsAnimDown = FALSE; 
	} 
 
	m_FinalSize = size; 
 
	//---------------------------------------------------------------- 
	// If the final size is more, that half-screen (in either x or y), 
	// CS_SAVEBITS may not save a screen content under the menu. So, 
	// we need to save a area under the shadows: 
	//--------------------------------------------------------------- 
	m_bSaveShadows =	(m_FinalSize.cx >= rectScreen.Width ()) || 
						(m_FinalSize.cy >= rectScreen.Height ()); 
 
	if (m_bAnimationIsDone || CBCGToolBar::IsCustomizeMode ()) 
	{ 
		if (!CBCGToolBar::IsCustomizeMode ()) 
		{ 
			size.cx += m_iShadowSize; 
			size.cy += m_iShadowSize; 
		} 
 
		if (m_pMenuCustomizationPage != NULL) 
		{ 
			SetWindowPos (NULL, -1, -1, size.cx, size.cy, 
						SWP_NOMOVE | SWP_NOZORDER | 
						SWP_NOACTIVATE); 
		} 
		else 
		{ 
			SetWindowPos (NULL, m_ptLocation.x, m_ptLocation.y, size.cx, size.cy, 
						SWP_NOZORDER | SWP_NOACTIVATE); 
		} 
	} 
 
	if (CBCGToolBar::IsCustomizeMode ()) 
	{ 
		pMenuBar->AdjustLocations (); 
	} 
 
	//--------------------------------------------------- 
	// Parent button maybe covered by shadow, repaint it: 
	//--------------------------------------------------- 
	if (m_iShadowSize != 0 && 
		m_bAnimationIsDone &&  
		!CBCGToolBar::IsCustomizeMode () && 
		m_pParentBtn != NULL && 
		m_pParentBtn->GetParentWnd () != NULL) 
	{ 
		CWnd* pWndParent = m_pParentBtn->GetParentWnd (); 
 
		CRect rectInter; 
 
		CRect rectMenu; 
		GetWindowRect (rectMenu); 
 
		CRect rectShadowRight (CPoint (rectMenu.right + 1, rectMenu.top),  
					CSize (m_iShadowSize, rectMenu.Height () + m_iShadowSize)); 
		pWndParent->ScreenToClient (rectShadowRight); 
		if (rectInter.IntersectRect (rectShadowRight, m_pParentBtn->m_rect)) 
		{ 
			pWndParent->InvalidateRect (m_pParentBtn->m_rect); 
			pWndParent->UpdateWindow (); 
		} 
		else 
		{ 
			CRect rectShadowBottom (CPoint (rectMenu.left, rectMenu.bottom + 1), 
						CSize (rectMenu.Width () + m_iShadowSize, m_iShadowSize)); 
			pWndParent->ScreenToClient (rectShadowBottom); 
			if (rectInter.IntersectRect (rectShadowBottom, m_pParentBtn->m_rect)) 
			{ 
				pWndParent->InvalidateRect (m_pParentBtn->m_rect); 
				pWndParent->UpdateWindow (); 
			} 
		} 
	} 
} 
//**************************************************************************************** 
void CBCGPopupMenu::OnDestroy()  
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	//--------------------------------------------------------- 
	// First, maybe we have a dragged menu item. Remove it now: 
	//--------------------------------------------------------- 
	if (pMenuBar->m_pDragButton != NULL && 
		!pMenuBar->m_bIsDragCopy) 
	{ 
		pMenuBar->RemoveButton ( 
			pMenuBar->ButtonToIndex (pMenuBar->m_pDragButton)); 
		pMenuBar->m_pDragButton = NULL; 
	} 
 
	if (m_pParentBtn != NULL) 
	{ 
		ASSERT (m_pParentBtn->m_pPopupMenu == this); 
 
		SaveState (); 
 
		m_pParentBtn->m_pPopupMenu = NULL; 
		m_pParentBtn->m_bClickedOnMenu = FALSE; 
 
		CBCGPopupMenu* pParentMenu = GetParentPopupMenu (); 
		if (pParentMenu != NULL) 
		{ 
			if (m_bAutoDestroyParent && !CBCGToolBar::IsCustomizeMode ()) 
			{ 
				//------------------------------------------- 
				// Automatically close the parent popup menu: 
				//------------------------------------------- 
				pParentMenu->SendMessage (WM_CLOSE); 
				m_pParentBtn = NULL; 
			} 
			else if (pParentMenu->m_iShadowSize > 0 && 
				m_AnimationType != NO_ANIMATION) 
			{ 
				//-------------------- 
				// Redraw parent menu: 
				//-------------------- 
				pParentMenu->ShowWindow (SW_HIDE); 
				pParentMenu->UpdateBottomWindows (); 
				pParentMenu->ShowWindow (SW_SHOWNOACTIVATE); 
			} 
		} 
		else 
		{ 
			CBCGMenuBar* pParentMenuBar = m_pParentBtn == NULL ? NULL : 
				DYNAMIC_DOWNCAST (CBCGMenuBar, m_pParentBtn->m_pWndParent); 
 
			if (pParentMenuBar == NULL) 
			{ 
				CBCGMenuBar::SetShowAllCommands (FALSE); 
			} 
		} 
	} 
	else 
	{ 
		CBCGMenuBar::SetShowAllCommands (FALSE); 
	} 
 
	if (m_pMenuCustomizationPage != NULL) 
	{ 
		m_pMenuCustomizationPage->CloseContextMenu (this); 
	} 
				 
	//------------------------------------------------ 
	// Inform the main frame about the menu detsroyng: 
	//------------------------------------------------ 
	CFrameWnd* pWndMain = GetTopLevelFrame (); 
 
	CBCGMDIFrameWnd* pMainFrame = DYNAMIC_DOWNCAST (CBCGMDIFrameWnd, pWndMain); 
	if (pMainFrame != NULL) 
	{ 
		pMainFrame->OnClosePopupMenu (this); 
	} 
	else	// Maybe, SDI frame... 
	{ 
		CBCGFrameWnd* pFrame = DYNAMIC_DOWNCAST (CBCGFrameWnd, pWndMain); 
		if (pFrame != NULL) 
		{ 
			pFrame->OnClosePopupMenu (this); 
		} 
		else	// Maybe, OLE frame... 
		{ 
			CBCGOleIPFrameWnd* pOleFrame =  
				DYNAMIC_DOWNCAST (CBCGOleIPFrameWnd, pWndMain); 
			if (pOleFrame != NULL) 
			{ 
				pOleFrame->OnClosePopupMenu (this); 
			} 
		} 
	} 
 
	CMiniFrameWnd::OnDestroy(); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::PostNcDestroy()  
{ 
	if (m_pParentBtn != NULL) 
	{ 
		m_pParentBtn->OnCancelMode (); 
	} 
		 
	CMiniFrameWnd::PostNcDestroy(); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::SaveState () 
{ 
	if (!CBCGToolBar::IsCustomizeMode ()) 
	{ 
		return; 
	} 
 
	if (m_pParentBtn == NULL) 
	{ 
		return; 
	} 
 
	ASSERT_VALID (m_pParentBtn); 
 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	HMENU hmenu = pMenuBar->ExportToMenu (); 
	ASSERT (hmenu != NULL); 
 
	m_pParentBtn->CreateFromMenu (hmenu); 
	::DestroyMenu (hmenu); 
 
	CBCGPopupMenu* pParentMenu = GetParentPopupMenu (); 
	if (pParentMenu != NULL) 
	{ 
		pParentMenu->SaveState (); 
	} 
} 
//**************************************************************************************** 
void CBCGPopupMenu::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	ASSERT_VALID (this); 
 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
#ifdef _DEBUG 
	if (m_pParentBtn != NULL) 
	{ 
		ASSERT_VALID (m_pParentBtn); 
		ASSERT (m_pParentBtn->m_pPopupMenu == this); 
	} 
#endif // _DEBUG 
 
	BOOL bHightlightWasChanged = FALSE; 
 
	switch (nChar) 
	{ 
	case VK_RIGHT: 
		{ 
			//------------------------------------------- 
			// Save animation type and disable animation: 
			//------------------------------------------- 
			ANIMATION_TYPE animType = m_AnimationType; 
			m_AnimationType = NO_ANIMATION; 
 
			//------------------------------- 
			// Try to open next cascade menu: 
			//------------------------------- 
			CBCGToolbarMenuButton* pSelItem = GetSelItem (); 
			if (pSelItem != NULL &&  
				(pSelItem->m_nID == (UINT) -1 || pSelItem->m_nID == 0) && 
				pSelItem->OpenPopupMenu ()) 
			{ 
				if (pSelItem->m_pPopupMenu != NULL) 
				{ 
					//-------------------------- 
					// Select a first menu item: 
					//-------------------------- 
					if (GetSelItem () == pSelItem) 
					{ 
						pSelItem->m_pPopupMenu->OnKeyDown (VK_HOME, 0, 0); 
					} 
				} 
			} 
			else 
			{ 
				//------------------------------------------------------ 
				// No next menu, first try to go to the parent menu bar: 
				//------------------------------------------------------ 
				CBCGToolBar* pToolBar = GetParentToolBar (); 
				if (pToolBar != NULL &&  
					!pToolBar->IsKindOf (RUNTIME_CLASS (CBCGPopupMenuBar))) 
				{ 
					pToolBar->NextMenu (); 
				} 
				else 
				{ 
					//------------------------------------------------------ 
					// Close the current menu and move control to the parent 
					// popup menu: 
					//------------------------------------------------------ 
					CBCGPopupMenu* pParenMenu = GetParentPopupMenu (); 
					if (pParenMenu != NULL) 
					{ 
						pParenMenu->SendMessage (WM_KEYDOWN, VK_RIGHT); 
					} 
				} 
			} 
 
			//------------------------ 
			// Restore animation type: 
			//------------------------ 
			m_AnimationType = animType; 
		} 
		return; 
				 
	case VK_LEFT: 
		{ 
			CBCGToolBar* pToolBar = GetParentToolBar (); 
			if (pToolBar != NULL) 
			{ 
				pToolBar->PrevMenu (); 
			} 
			else if (m_pParentBtn != NULL && m_pParentBtn->IsDroppedDown ())		 
			{ 
				CloseMenu (); 
			} 
		} 
		return; 
 
	case VK_DOWN: 
		if ((::GetAsyncKeyState (VK_CONTROL) & 0x8000) &&	// Ctrl+Down 
			!pMenuBar->m_bAreAllCommandsShown) 
		{ 
			ShowAllCommands (); 
			break; 
		} 
 
	case VK_UP: 
	case VK_HOME: 
	case VK_END: 
		bHightlightWasChanged = TRUE; 
 
	case VK_RETURN: 
		if (!CBCGToolBar::IsCustomizeMode ()) 
		{ 
			pMenuBar->OnKey (nChar); 
		} 
		break; 
 
	case VK_ESCAPE: 
		CloseMenu (TRUE); 
		return; 
 
	default: 
		if (pMenuBar->OnKey (nChar)) 
		{ 
			return; 
		} 
		else 
		{ 
			CMiniFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags); 
		} 
	} 
 
	if (bHightlightWasChanged && 
		m_bScrollable && pMenuBar->m_iHighlighted >= 0) 
	{ 
		//--------------------------------------- 
		// Maybe, selected item is invisible now? 
		//--------------------------------------- 
		CBCGToolbarButton* pItem = pMenuBar->GetButton (pMenuBar->m_iHighlighted); 
		if (pItem == NULL && pMenuBar->GetRowHeight () == 0) 
		{ 
			ASSERT (FALSE); 
		} 
		else 
		{ 
			CRect rectBar; 
			pMenuBar->GetClientRect (rectBar); 
 
			int iOffset = pMenuBar->GetOffset (); 
			int iOffsetDelta = 0; 
 
			if (pItem->Rect ().top  rectBar.top) 
			{ 
				//--------------------- 
				// Scroll up is needed! 
				//--------------------- 
				iOffsetDelta = (pItem->Rect ().top - rectBar.top) /  
					pMenuBar->GetRowHeight () - 1; 
			} 
			else if (pItem->Rect ().bottom > rectBar.bottom) 
			{ 
				//----------------------- 
				// Scroll down is needed! 
				//----------------------- 
				iOffsetDelta = (pItem->Rect ().bottom - rectBar.bottom) /  
					pMenuBar->GetRowHeight () + 1; 
			} 
 
			if (iOffsetDelta != 0) 
			{ 
				int iTotalRows = m_FinalSize.cy / pMenuBar->GetRowHeight () - 2; 
 
				iOffset += iOffsetDelta; 
				iOffset = min (max (0, iOffset),  
					pMenuBar->m_Buttons.GetCount () - iTotalRows - 1); 
 
				pMenuBar->SetOffset (iOffset); 
				pMenuBar->AdjustLayout (); 
 
				InvalidateRect (m_rectScrollDn); 
				InvalidateRect (m_rectScrollUp); 
			} 
		} 
	} 
} 
//**************************************************************************************** 
CBCGPopupMenu* CBCGPopupMenu::GetParentPopupMenu () const 
{ 
	if (m_pParentBtn == NULL) 
	{ 
		return NULL; 
	} 
 
	CBCGPopupMenuBar* pParentBar =  
		DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pParentBtn->m_pWndParent); 
	if (pParentBar != NULL) 
	{ 
		CBCGPopupMenu* pParentMenu = 
			DYNAMIC_DOWNCAST (CBCGPopupMenu, pParentBar->GetParentFrame ()); 
		ASSERT_VALID (pParentMenu); 
 
		return pParentMenu; 
	} 
	else 
	{ 
		return NULL; 
	} 
} 
//**************************************************************************************** 
CBCGToolBar* CBCGPopupMenu::GetParentToolBar () const 
{ 
	if (m_pParentBtn == NULL) 
	{ 
		return NULL; 
	} 
 
	CBCGToolBar* pParentBar =  
		DYNAMIC_DOWNCAST (CBCGToolBar, m_pParentBtn->m_pWndParent); 
	return pParentBar; 
} 
//**************************************************************************************** 
CBCGToolbarMenuButton* CBCGPopupMenu::GetSelItem () 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	return DYNAMIC_DOWNCAST (CBCGToolbarMenuButton, 
							pMenuBar->GetHighlightedButton ()); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::CloseMenu (BOOL bSetFocusToBar) 
{ 
	m_bTobeDstroyed = TRUE; 
 
	SaveState (); 
 
	CBCGPopupMenu* pParentMenu = GetParentPopupMenu (); 
	CBCGToolBar* pParentToolBar = GetParentToolBar (); 
 
	CFrameWnd* pWndMain = GetTopLevelFrame (); 
	if (pParentMenu != NULL) 
	{ 
		m_bAutoDestroyParent = FALSE; 
		ActivatePopupMenu (pWndMain, pParentMenu); 
	} 
	else if (pParentToolBar != NULL) 
	{ 
		ActivatePopupMenu (pWndMain, NULL); 
 
		if (bSetFocusToBar) 
		{ 
			pParentToolBar->SetFocus (); 
		} 
	} 
	else 
	{ 
		ActivatePopupMenu (pWndMain, NULL); 
	} 
 
	SendMessage (WM_CLOSE); 
} 
//**************************************************************************************** 
int CBCGPopupMenu::InsertItem (const CBCGToolbarMenuButton& button, int iInsertAt) 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	return pMenuBar->InsertButton (button, iInsertAt); 
} 
//**************************************************************************************** 
int CBCGPopupMenu::InsertSeparator (int iInsertAt) 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	return pMenuBar->InsertSeparator (iInsertAt); 
} 
//**************************************************************************************** 
int CBCGPopupMenu::GetMenuItemCount () const 
{ 
	return m_wndMenuBar.m_Buttons.GetCount (); 
} 
//**************************************************************************************** 
CBCGToolbarMenuButton* CBCGPopupMenu::GetMenuItem (int iIndex) const 
{ 
	return (CBCGToolbarMenuButton*) m_wndMenuBar.GetButton (iIndex); 
} 
//**************************************************************************************** 
BOOL CBCGPopupMenu::RemoveItem (int iIndex) 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	return pMenuBar->RemoveButton (iIndex); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::RemoveAllItems () 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	pMenuBar->RemoveAllButtons (); 
} 
//**************************************************************************************** 
BOOL CBCGPopupMenu::OnEraseBkgnd(CDC* /*pDC*/)  
{ 
	return TRUE; 
} 
//**************************************************************************************** 
BOOL CBCGPopupMenu::ActivatePopupMenu (CFrameWnd* pTopFrame, CBCGPopupMenu* pPopupMenu) 
{ 
	ASSERT_VALID (pTopFrame); 
 
	BOOL bRes = TRUE; 
 
	CBCGMDIFrameWnd* pMainFrame = DYNAMIC_DOWNCAST (CBCGMDIFrameWnd, pTopFrame); 
	if (pMainFrame != NULL) 
	{ 
		bRes = pMainFrame->ShowPopupMenu (pPopupMenu); 
	} 
	else	// Maybe, SDI frame... 
	{ 
		CBCGFrameWnd* pFrame = DYNAMIC_DOWNCAST (CBCGFrameWnd, pTopFrame); 
		if (pFrame != NULL) 
		{ 
			bRes = pFrame->ShowPopupMenu (pPopupMenu); 
		} 
		else	// Maybe, OLE frame 
		{ 
			CBCGOleIPFrameWnd* pOleFrame =  
				DYNAMIC_DOWNCAST (CBCGOleIPFrameWnd, pTopFrame); 
			if (pOleFrame != NULL) 
			{ 
				bRes = pOleFrame->ShowPopupMenu (pPopupMenu); 
			} 
		} 
	} 
 
	if (!bRes) 
	{ 
		if (pPopupMenu != NULL && !pPopupMenu->m_bTobeDstroyed) 
		{ 
			pPopupMenu->CloseMenu (); 
		} 
 
		return FALSE; 
	} 
 
	if (pPopupMenu != NULL) 
	{ 
		CBCGPopupMenuBar* pMenuBar = pPopupMenu->GetMenuBar (); 
		ASSERT_VALID (pMenuBar); 
 
		CBCGPopupMenu* pParentMenu = DYNAMIC_DOWNCAST (CBCGPopupMenu, pMenuBar->GetParent ()); 
		if (pParentMenu != NULL && pParentMenu->GetParentButton () != NULL && 
			!pMenuBar->m_bAreAllCommandsShown) 
		{ 
			pMenuBar->InsertButton (CBCGShowAllButton ()); 
		} 
	} 
 
	return TRUE; 
} 
//************************************************************************************ 
void CBCGPopupMenu::OnActivateApp(BOOL bActive, HTASK /*hTask*/)  
{ 
	if (!bActive && !CBCGToolBar::IsCustomizeMode ()) 
	{ 
		SendMessage (WM_CLOSE); 
	} 
} 
//************************************************************************************* 
void CBCGPopupMenu::OnTimer(UINT nIDEvent)  
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	switch (nIDEvent) 
	{ 
	case iAnimTimerId: 
		if (!m_bAnimationIsDone) 
		{ 
			m_AnimSize.cy += pMenuBar->GetRowHeight (); 
			if (m_AnimationType == UNFOLD) 
			{ 
				m_AnimSize.cx += pMenuBar->GetColumnWidth (); 
			} 
 
			if (m_AnimSize.cy + m_iShadowSize >= m_FinalSize.cy || 
				(m_AnimationType == UNFOLD && m_AnimSize.cx + m_iShadowSize >= m_FinalSize.cx)) 
			{ 
				m_bAnimationIsDone = TRUE; 
 
				m_AnimSize.cx = m_FinalSize.cx + m_iShadowSize; 
				m_AnimSize.cy = m_FinalSize.cy + m_iShadowSize; 
 
				m_ptLocationAnim = m_ptLocation; 
 
				pMenuBar->SetOffset (0); 
				KillTimer (iAnimTimerId); 
			} 
			else 
			{ 
				if (m_bIsAnimDown) 
				{ 
					pMenuBar->SetOffset (pMenuBar->GetOffset () - 1); 
				} 
 
				if (!m_bIsAnimRight && m_AnimationType == UNFOLD) 
				{ 
					m_ptLocationAnim.x -= pMenuBar->GetColumnWidth (); 
				} 
 
				if (!m_bIsAnimDown) 
				{ 
					m_ptLocationAnim.y -= pMenuBar->GetRowHeight (); 
				} 
			} 
 
			SetWindowPos (NULL, m_ptLocationAnim.x, m_ptLocationAnim.y,  
				m_AnimSize.cx, m_AnimSize.cy, 
				SWP_NOZORDER | SWP_NOACTIVATE); 
 
			//---------------- 
			// Redraw borders: 
			//---------------- 
			CRect rectClient; 
			GetClientRect (rectClient); 
 
			InvalidateRect (CRect (	CPoint (rectClient.left, rectClient.top), 
									CSize (rectClient.Width (), iBorderSize))); 
			InvalidateRect (CRect (	CPoint (rectClient.left, rectClient.top), 
									CSize (iBorderSize, rectClient.Height ()))); 
			InvalidateRect (CRect (	CPoint (rectClient.right - iBorderSize, rectClient.top), 
									CSize (iBorderSize, rectClient.Height ()))); 
 
			//----------------------- 
			// Redraw scroll buttons: 
			//----------------------- 
			InvalidateRect (m_rectScrollUp); 
			InvalidateRect (m_rectScrollDn); 
		} 
		break; 
 
	case iScrollTimerId: 
		{ 
			CPoint point; 
			::GetCursorPos (&point); 
			ScreenToClient (&point); 
 
			int iOffset = pMenuBar->GetOffset (); 
 
			if (m_rectScrollUp.PtInRect (point) && m_iScrollMode  0 && 
				IsScrollUpAvailable ())	// Scroll Up 
			{ 
				pMenuBar->SetOffset (iOffset - 1); 
				pMenuBar->AdjustLayout (); 
			} 
			else if (m_rectScrollDn.PtInRect (point) && m_iScrollMode > 0 && 
				IsScrollDnAvailable ())	// Scroll Down 
			{ 
				pMenuBar->SetOffset (iOffset + 1); 
				pMenuBar->AdjustLayout (); 
			} 
			else 
			{ 
				KillTimer (iScrollTimerId); 
				m_iScrollMode = 0; 
				InvalidateRect (m_rectScrollDn); 
				InvalidateRect (m_rectScrollUp); 
			} 
		} 
		break; 
	} 
 
	CMiniFrameWnd::OnTimer(nIDEvent); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	CMiniFrameWnd::OnMouseMove(nFlags, point); 
 
	if (!m_bScrollable || m_iScrollMode != 0) 
	{ 
		return; 
	} 
	 
	if (m_rectScrollUp.PtInRect (point) && IsScrollUpAvailable ()) 
	{ 
		m_iScrollMode = -1; 
		InvalidateRect (m_rectScrollUp); 
	} 
	else if (m_rectScrollDn.PtInRect (point) && IsScrollDnAvailable ()) 
	{ 
		m_iScrollMode = 1; 
		InvalidateRect (m_rectScrollDn); 
	} 
	else 
	{ 
		m_iScrollMode = 0; 
	} 
 
	if (m_iScrollMode != 0) 
	{ 
		SetTimer (iScrollTimerId, iScrollTimerDuration, NULL); 
	} 
} 
//**************************************************************************************** 
BOOL CBCGPopupMenu::IsScrollUpAvailable () 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	return pMenuBar->GetOffset () > 0; 
} 
//**************************************************************************************** 
BOOL CBCGPopupMenu::IsScrollDnAvailable () 
{ 
	CBCGPopupMenuBar* pMenuBar = GetMenuBar (); 
	ASSERT_VALID (pMenuBar); 
 
	if (pMenuBar->GetRowHeight () == 0) 
	{ 
		return FALSE; 
	} 
 
	int iTotalRows = m_FinalSize.cy / pMenuBar->GetRowHeight () - 1; 
	return (pMenuBar->GetOffset ()   
		pMenuBar->m_Buttons.GetCount () - iTotalRows); 
} 
//**************************************************************************************** 
void CBCGPopupMenu::CollapseSubmenus () 
{ 
	for (POSITION pos = m_wndMenuBar.m_Buttons.GetHeadPosition (); pos != NULL;) 
	{ 
		CBCGToolbarButton* pButton =  
			(CBCGToolbarButton*) m_wndMenuBar.m_Buttons.GetNext (pos); 
		ASSERT (pButton != NULL); 
 
		pButton->OnCancelMode (); 
	} 
} 
//**************************************************************************************** 
void CBCGPopupMenu::DrawImage (CDC* pDC, const CRect& rect, int iImage, BOOL bDrawFrame) 
{ 
	CRect rectImage (CPoint (0, 0), CMenuImages::Size ()); 
 
	CRect rectFill = rect; 
	rectFill.top -= 2; 
 
	pDC->FillRect (rectFill, &globalData.brBtnFace); 
 
	CPoint point ( 
		rect.left + (rect.Width () - rectImage.Width ()) / 2, 
		rect.top + (rect.Height () - rectImage.Height ()) / 2); 
 
	CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iImage, point); 
 
	if (bDrawFrame) 
	{ 
		pDC->Draw3dRect (rect, 
			globalData.clrBtnHilite, 
			globalData.clrBtnShadow); 
	} 
} 
//**************************************************************************************** 
void CBCGPopupMenu::ShowAllCommands () 
{ 
	CBCGToolbarMenuButton* pParentMenuButton = 
		DYNAMIC_DOWNCAST (CBCGToolbarMenuButton, m_pParentBtn); 
	if (pParentMenuButton != NULL) 
	{ 
		CBCGMenuBar::SetShowAllCommands (); 
 
		// Play standard menu popup sound! 
		::PlaySound (_T("MenuPopup"), NULL, SND_ASYNC | SND_NODEFAULT); 
 
		ShowWindow (SW_HIDE); 
		m_bShown = FALSE; 
 
		if (m_bmpShadowRight.GetSafeHandle () != NULL) 
		{ 
			m_bmpShadowRight.DeleteObject (); 
		} 
		 
		if (m_bmpShadowBottom.GetSafeHandle () != NULL) 
		{ 
			m_bmpShadowBottom.DeleteObject (); 
		} 
 
		InitMenuBar (); 
		UpdateBottomWindows (); 
 
		ShowWindow (SW_SHOWNOACTIVATE); 
 
		if (pParentMenuButton->m_pWndParent != NULL  
			&& ::IsWindow (pParentMenuButton->m_pWndParent->m_hWnd)) 
		{ 
			pParentMenuButton->m_pWndParent->InvalidateRect ( 
				pParentMenuButton->Rect ()); 
			pParentMenuButton->m_pWndParent->UpdateWindow (); 
		} 
	} 
} 
//************************************************************************************** 
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); 
 
}