www.pudn.com > vc开发的精美界面.zip > BCGFrameImpl.cpp


//******************************************************************************* 
// 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. 
//  
// For the latest updates to this library, check my site: 
// http://welcome.to/bcgsoft 
//  
// Stas Levin  
//******************************************************************************* 
 
// BCGFrameImpl.cpp: implementation of the CBCGFrameImpl class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
 
#include "BCGFrameImpl.h" 
#include "BCGToolBar.h" 
#include "BCGDialogBar.h" 
#include "BCGSizingControlBar.h" 
#include "BCGMenuBar.h" 
#include "bcglocalres.h" 
#include "bcgbarres.h" 
#include "BCGPopupMenu.h" 
#include "BCGToolbarMenuButton.h" 
#include "BCGWorkspace.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
extern CObList	gAllToolbars; 
extern CBCGWorkspace* g_pWorkspace; 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CBCGFrameImpl::CBCGFrameImpl(CFrameWnd* pFrame) : 
	m_pFrame (pFrame), 
	m_pActivePopupMenu (NULL), 
	m_uiUserToolbarFirst ((UINT)-1), 
	m_uiUserToolbarLast ((UINT)-1), 
	m_pMenuBar (NULL), 
	m_hDefaultMenu (NULL), 
	m_nIDDefaultResource (0) 
{ 
	ASSERT_VALID (m_pFrame); 
} 
//************************************************************************************** 
CBCGFrameImpl::~CBCGFrameImpl() 
{ 
	//----------------------------- 
	// Clear user-defined toolbars: 
	//----------------------------- 
	while (!m_listUserDefinedToolbars.IsEmpty ()) 
	{ 
		delete m_listUserDefinedToolbars.RemoveHead (); 
	} 
} 
//************************************************************************************** 
void CBCGFrameImpl::OnCloseFrame() 
{ 
	//---------------------------------------------------------------------- 
	// Automatically load state and frame position if CBCGWorkspace is used: 
	//---------------------------------------------------------------------- 
	if (g_pWorkspace != NULL) 
	{ 
		g_pWorkspace->OnClosingMainFrame (this); 
 
		//--------------------------- 
		// Store the Windowplacement: 
		//--------------------------- 
		if (::IsWindow (m_pFrame->GetSafeHwnd ())) 
		{ 
			WINDOWPLACEMENT wp; 
			wp.length = sizeof (WINDOWPLACEMENT); 
 
			if (m_pFrame->GetWindowPlacement (&wp)) 
			{ 
				//--------------------------- 
				// Make sure we don't pop up  
				// minimized the next time 
				//--------------------------- 
				if (wp.showCmd != SW_SHOWMAXIMIZED) 
				{ 
					wp.showCmd = SW_SHOWNORMAL; 
				} 
 
				g_pWorkspace->StoreWindowPlacement ( 
					wp.rcNormalPosition, wp.flags, wp.showCmd); 
			} 
		} 
 
	} 
} 
//************************************************************************************** 
void CBCGFrameImpl::RestorePosition(CREATESTRUCT& cs) 
{ 
	if (g_pWorkspace != NULL) 
	{ 
		CRect rectNormal (CPoint (cs.x, cs.y), CSize (cs.cx, cs.cy)); 
		int nFlags = 0; 
		int nShowCmd = SW_SHOWNORMAL; 
 
		if (!g_pWorkspace->LoadWindowPlacement (rectNormal, nFlags, nShowCmd)) 
		{ 
			return; 
		} 
 
		if (nShowCmd != SW_MAXIMIZE) 
		{ 
			nShowCmd = SW_SHOWNORMAL; 
		} 
 
		switch (AfxGetApp()->m_nCmdShow) 
		{ 
		case SW_MAXIMIZE: 
		case SW_MINIMIZE: 
			break;	// don't change! 
 
		default: 
			AfxGetApp()->m_nCmdShow = nShowCmd; 
		} 
 
		CRect rectDesktop; 
		CRect rectInter; 
 
		if (::SystemParametersInfo (SPI_GETWORKAREA, 0, &rectDesktop, 0) && 
			rectInter.IntersectRect (&rectDesktop, &rectNormal)) 
		{ 
			cs.x = rectNormal.left; 
			cs.y = rectNormal.top; 
			cs.cx = rectNormal.Width (); 
			cs.cy = rectNormal.Height (); 
		} 
	} 
} 
//************************************************************************************** 
void CBCGFrameImpl::OnLoadFrame() 
{ 
	//--------------------------------------------------- 
	// Automatically load state if CBCGWorkspace is used: 
	//--------------------------------------------------- 
	if (g_pWorkspace != NULL) 
	{ 
		g_pWorkspace->LoadState (0, this); 
	} 
} 
//************************************************************************************** 
void CBCGFrameImpl::LoadUserToolbars () 
{ 
	if (m_uiUserToolbarFirst == (UINT) -1 || 
		m_uiUserToolbarLast == (UINT) -1) 
	{ 
		return; 
	} 
 
	for (UINT uiNewToolbarID = m_uiUserToolbarFirst; 
		uiNewToolbarID <= m_uiUserToolbarLast; 
		uiNewToolbarID ++) 
	{ 
		CBCGToolBar* pNewToolbar = new CBCGToolBar; 
		if (!pNewToolbar->Create (m_pFrame,  
			dwDefaultToolbarStyle, 
			uiNewToolbarID)) 
		{ 
			TRACE0 ("Failed to create a new toolbar!\n"); 
			delete pNewToolbar; 
			continue; 
		} 
 
		if (!pNewToolbar->LoadState (m_strControlBarRegEntry)) 
		{ 
			pNewToolbar->DestroyWindow (); 
			delete pNewToolbar; 
		} 
		else 
		{ 
			pNewToolbar->SetBarStyle (pNewToolbar->GetBarStyle () | 
				CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); 
			pNewToolbar->EnableDocking (CBRS_ALIGN_ANY); 
 
			m_pFrame->DockControlBar (pNewToolbar); 
			m_listUserDefinedToolbars.AddTail (pNewToolbar); 
		} 
	} 
} 
//********************************************************************************************** 
void CBCGFrameImpl::SaveUserToolbars () 
{ 
	for (POSITION pos = m_listUserDefinedToolbars.GetHeadPosition (); pos != NULL;) 
	{ 
		CBCGToolBar* pUserToolBar =  
			(CBCGToolBar*) m_listUserDefinedToolbars.GetNext (pos); 
		ASSERT_VALID(pUserToolBar); 
 
		pUserToolBar->SaveState (m_strControlBarRegEntry); 
	} 
} 
//********************************************************************************************** 
CBCGToolBar* CBCGFrameImpl::GetUserBarByIndex (int iIndex) const 
{ 
	POSITION pos = m_listUserDefinedToolbars.FindIndex (iIndex); 
	if (pos == NULL) 
	{ 
		return NULL; 
	} 
 
	CBCGToolBar* pUserToolBar =  
		(CBCGToolBar*) m_listUserDefinedToolbars.GetAt (pos); 
	ASSERT_VALID (pUserToolBar); 
 
	return pUserToolBar; 
} 
//********************************************************************************************** 
BOOL CBCGFrameImpl::IsUserDefinedToolbar (const CBCGToolBar* pToolBar) const 
{ 
	ASSERT_VALID (pToolBar); 
 
	UINT uiCtrlId = pToolBar->GetDlgCtrlID (); 
	return	uiCtrlId >= m_uiUserToolbarFirst && 
			uiCtrlId <= m_uiUserToolbarLast; 
} 
//******************************************************************************************* 
BOOL CBCGFrameImpl::IsDockStateValid (const CDockState& state) 
{ 
	//---------------------------------------------------------------- 
	// This function helps to avoid GPF during CFrameWnd::LoadBarState 
	// execution: when one of the previously saved toolbars is not 
	// created, LoadBarState fails. 
	//---------------------------------------------------------------- 
 
	for (int i = 0; i < state.m_arrBarInfo.GetSize (); i ++) 
	{ 
		CControlBarInfo* pInfo = (CControlBarInfo*) state.m_arrBarInfo [i]; 
		ASSERT (pInfo != NULL); 
 
		if (!pInfo->m_bFloating) 
		{ 
			//--------------------------------------- 
			// Find the control bar with the same ID: 
			//--------------------------------------- 
			if (m_pFrame->GetControlBar (pInfo->m_nBarID) == NULL) 
			{ 
				TRACE (_T("CBCGFrameImpl::IsDockStateValid ControlBar %x is not valid!\n"), pInfo->m_nBarID); 
				return FALSE; 
			} 
		} 
	} 
 
	return TRUE; 
} 
//********************************************************************************** 
void CBCGFrameImpl::InitUserToobars (	LPCTSTR lpszRegEntry, 
										UINT uiUserToolbarFirst,  
										UINT uiUserToolbarLast) 
{ 
	ASSERT (uiUserToolbarLast >= uiUserToolbarFirst); 
 
	if (uiUserToolbarFirst == (UINT) -1 || 
		uiUserToolbarFirst == (UINT) -1) 
	{ 
		ASSERT (FALSE); 
		return; 
	} 
 
	m_uiUserToolbarFirst = uiUserToolbarFirst; 
	m_uiUserToolbarLast = uiUserToolbarLast; 
 
	// ET: get Path automatically from workspace if needed 
	m_strControlBarRegEntry = (lpszRegEntry == NULL) ?  
		( g_pWorkspace ? g_pWorkspace->GetRegSectionPath() : _T("") ) 
		: lpszRegEntry; 
} 
//************************************************************************************** 
const CBCGToolBar* CBCGFrameImpl::CreateNewToolBar (LPCTSTR lpszName) 
{ 
	ASSERT (lpszName != NULL); 
 
	if (m_uiUserToolbarFirst == (UINT)-1 || 
		m_uiUserToolbarLast == (UINT)-1) 
	{ 
		TRACE (_T("User-defined toolbars IDs are none defined!\n")); 
		return NULL; 
	} 
 
	int iMaxToolbars = m_uiUserToolbarLast - m_uiUserToolbarFirst + 1; 
	if (m_listUserDefinedToolbars.GetCount () == iMaxToolbars) 
	{ 
		CBCGLocalResource locaRes; 
 
		CString strError; 
		strError.Format (IDS_BCGBARRES_TOO_MANY_TOOLBARS_FMT, iMaxToolbars); 
 
		AfxMessageBox (strError, MB_OK | MB_ICONASTERISK); 
		return NULL; 
	} 
 
	//----------------------- 
	// Find a new toolbar id: 
	//----------------------- 
	UINT uiNewToolbarID; 
 
	for (uiNewToolbarID = m_uiUserToolbarFirst; 
		uiNewToolbarID <= m_uiUserToolbarLast; 
		uiNewToolbarID ++) 
	{ 
		BOOL bUsed = FALSE; 
 
		for (POSITION pos = m_listUserDefinedToolbars.GetHeadPosition ();  
			!bUsed && pos != NULL;) 
		{ 
			CBCGToolBar* pUserToolBar =  
				(CBCGToolBar*) m_listUserDefinedToolbars.GetNext (pos); 
			ASSERT_VALID(pUserToolBar); 
 
			bUsed = (pUserToolBar->GetDlgCtrlID () == (int) uiNewToolbarID); 
		} 
 
		if (!bUsed) 
		{ 
			break; 
		} 
	} 
 
	if (uiNewToolbarID >= m_uiUserToolbarLast) 
	{ 
		TRACE0 ("Can't find non-used toolbar number!\n"); 
		return NULL; 
	} 
 
	CBCGToolBar* pNewToolbar = new CBCGToolBar; 
	if (!pNewToolbar->Create (m_pFrame, 
		dwDefaultToolbarStyle, 
		uiNewToolbarID)) 
	{ 
		TRACE0 ("Failed to create a new toolbar!\n"); 
		delete pNewToolbar; 
		return NULL; 
	} 
 
	pNewToolbar->SetWindowText (lpszName); 
 
	pNewToolbar->SetBarStyle (pNewToolbar->GetBarStyle () | 
		CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); 
	pNewToolbar->EnableDocking (CBRS_ALIGN_ANY); 
	 
	m_pFrame->FloatControlBar (pNewToolbar, 
		CPoint (::GetSystemMetrics (SM_CXFULLSCREEN) / 2,  
				::GetSystemMetrics (SM_CYFULLSCREEN) / 2)); 
	m_pFrame->RecalcLayout (); 
 
	m_listUserDefinedToolbars.AddTail (pNewToolbar); 
	return pNewToolbar; 
} 
//************************************************************************************** 
BOOL CBCGFrameImpl::DeleteToolBar (CBCGToolBar* pToolBar) 
{ 
	ASSERT_VALID (pToolBar); 
 
	POSITION pos = m_listUserDefinedToolbars.Find (pToolBar); 
	if (pos == NULL) 
	{ 
		return FALSE; 
	} 
 
	m_listUserDefinedToolbars.RemoveAt (pos); 
	pToolBar->RemoveStateFromRegistry (m_strControlBarRegEntry); 
 
	pToolBar->DestroyWindow (); 
	delete pToolBar; 
 
	m_pFrame->RecalcLayout (); 
	return TRUE; 
} 
//******************************************************************************************* 
void CBCGFrameImpl::SetMenuBar (CBCGMenuBar* pMenuBar) 
{ 
	ASSERT_VALID (pMenuBar); 
	ASSERT (m_pMenuBar == NULL);	// Method should be called once! 
 
	m_pMenuBar = pMenuBar; 
 
	m_hDefaultMenu=*m_pFrame->GetMenu(); 
 
	// ET: Better support for dynamic menu 
	m_pMenuBar->OnDefaultMenuLoaded (m_hDefaultMenu); 
	m_pMenuBar->CreateFromMenu (m_hDefaultMenu, TRUE /* Default menu */); 
 
	m_pFrame->SetMenu (NULL); 
	 
	m_pMenuBar->SetDefaultMenuResId (m_nIDDefaultResource); 
} 
//******************************************************************************************* 
BOOL CBCGFrameImpl::ProcessKeyboard (int nKey) 
{ 
	if (m_pActivePopupMenu != NULL && 
		::IsWindow (m_pActivePopupMenu->m_hWnd)) 
	{ 
		m_pActivePopupMenu->SendMessage (WM_KEYDOWN, nKey); 
		return TRUE; 
	} 
 
	if (!CBCGToolBar::IsCustomizeMode () && 
		(::GetAsyncKeyState (VK_MENU) & 0x8000))	// ALT is pressed) 
	{ 
		if (OnMenuChar (nKey)) 
		{ 
			return TRUE; 
		} 
 
		ASSERT_VALID (m_pFrame); 
		m_pFrame->SetFocus (); 
	} 
 
	return FALSE; 
} 
//******************************************************************************************* 
BOOL CBCGFrameImpl::ProcessMouseClick (UINT uiMsg, POINT pt, HWND hwnd) 
{ 
	//------------------------------------------------ 
	// Maybe user start drag the button with control? 
	//------------------------------------------------ 
	if (uiMsg == WM_LBUTTONDOWN && 
		(CBCGToolBar::IsCustomizeMode () || 
		(::GetAsyncKeyState (VK_MENU) & 0x8000)))	// ALT is pressed 
	{ 
		for (POSITION posTlb = gAllToolbars.GetHeadPosition (); posTlb != NULL;) 
		{ 
			CBCGToolBar* pToolBar = (CBCGToolBar*) gAllToolbars.GetNext (posTlb); 
			ASSERT (pToolBar != NULL); 
 
			if (CWnd::FromHandlePermanent (pToolBar->m_hWnd) != NULL) 
			{ 
				ASSERT_VALID(pToolBar); 
 
				CPoint ptToolBar = pt; 
				pToolBar->ScreenToClient (&ptToolBar); 
 
				int iHit = pToolBar->HitTest (ptToolBar); 
				if (iHit >= 0) 
				{ 
					CBCGToolbarButton* pButton = pToolBar->GetButton (iHit); 
					ASSERT_VALID (pButton); 
 
					if (pButton->GetHwnd () != NULL && 
						pButton->GetHwnd () == hwnd && 
						pButton->Rect ().PtInRect (ptToolBar)) 
					{ 
						pToolBar->SendMessage (WM_LBUTTONDOWN,  
							0, MAKELPARAM (ptToolBar.x, ptToolBar.y)); 
						return TRUE; 
					} 
 
					break; 
				} 
			} 
		} 
	} 
 
	if (!CBCGToolBar::IsCustomizeMode () && 
		m_pActivePopupMenu != NULL && 
		::IsWindow (m_pActivePopupMenu->m_hWnd)) 
	{ 
		CRect rectMenu; 
		m_pActivePopupMenu->GetWindowRect (rectMenu); 
 
		if (!rectMenu.PtInRect (pt)) 
		{ 
			//-------------------------------------------- 
			// Maybe secondary click on the parent button? 
			//-------------------------------------------- 
			CBCGToolbarMenuButton* pParentButton =  
				m_pActivePopupMenu->GetParentButton (); 
			if (pParentButton != NULL) 
			{ 
				CWnd* pWndParent = pParentButton->GetParentWnd (); 
				if (pWndParent != NULL) 
				{ 
					CPoint ptClient = pt; 
					pWndParent->ScreenToClient (&ptClient); 
 
					if (pParentButton->Rect ().PtInRect (ptClient)) 
					{ 
						//----------------------------- 
						// Secondary click, do nothing! 
						//----------------------------- 
						if (!pWndParent->IsKindOf (RUNTIME_CLASS (CBCGPopupMenuBar))) 
						{ 
							m_pActivePopupMenu->SendMessage (WM_CLOSE); 
						} 
 
						return TRUE; 
					} 
				} 
			} 
 
			m_pActivePopupMenu->SendMessage (WM_CLOSE); 
 
			CWnd* pWndFocus = CWnd::GetFocus (); 
			if (pWndFocus != NULL && pWndFocus->IsKindOf (RUNTIME_CLASS (CBCGToolBar))) 
			{ 
				m_pFrame->SetFocus (); 
			} 
		} 
	} 
 
	return FALSE; 
} 
//******************************************************************************************* 
BOOL CBCGFrameImpl::ProcessMouseMove (POINT pt) 
{ 
	if (!CBCGToolBar::IsCustomizeMode () && 
		m_pActivePopupMenu != NULL) 
	{ 
		CRect rectMenu; 
		m_pActivePopupMenu->GetWindowRect (rectMenu); 
 
		if (rectMenu.PtInRect (pt) || 
			m_pActivePopupMenu->GetMenuBar ()->FindDestBar (pt) != NULL) 
		{ 
			return FALSE;	// Default processing 
		} 
 
		return TRUE;		// Active menu "capturing" 
	} 
 
	return FALSE;	// Default processing 
} 
//******************************************************************************************* 
BOOL CBCGFrameImpl::OnShowPopupMenu (CBCGPopupMenu* pMenuPopup, CFrameWnd* /*pWndFrame*/) 
{ 
	m_pActivePopupMenu = pMenuPopup; 
 
	if (pMenuPopup != NULL && !CBCGToolBar::IsCustomizeMode ()) 
	{ 
		ASSERT_VALID (pMenuPopup); 
 
		CControlBar* pTopLevelBar = NULL; 
 
		for (CBCGPopupMenu* pMenu = pMenuPopup; pMenu != NULL; 
			pMenu = pMenu->GetParentPopupMenu ()) 
		{ 
			CBCGToolbarMenuButton* pParentButton = pMenu->GetParentButton (); 
			if (pParentButton == NULL) 
			{ 
				break; 
			} 
		 
			pTopLevelBar =  
				DYNAMIC_DOWNCAST (CControlBar, pParentButton->GetParentWnd ()); 
		} 
 
		if (pTopLevelBar != NULL &&  
			!pTopLevelBar->IsKindOf (RUNTIME_CLASS (CBCGPopupMenuBar))) 
		{ 
			ASSERT_VALID (pTopLevelBar); 
 
			if (!pTopLevelBar->IsFloating () && 
				::GetFocus () != pTopLevelBar->GetSafeHwnd ()) 
			{ 
				pTopLevelBar->SetFocus (); 
			} 
		} 
	} 
 
	return TRUE; 
} 
//************************************************************************************* 
void CBCGFrameImpl::DockControlBarLeftOf(CControlBar* pBar, CControlBar* pLeftOf) 
{ 
	ASSERT_VALID (m_pFrame); 
	ASSERT_VALID (pBar); 
	ASSERT_VALID (pLeftOf); 
 
	CRect rect; 
	DWORD dw; 
	UINT n; 
	 
	// get MFC to adjust the dimensions of all docked ToolBars 
	// so that GetWindowRect will be accurate 
	m_pFrame->RecalcLayout(TRUE); 
	 
	pLeftOf->GetWindowRect(&rect); 
	rect.OffsetRect(1,1); 
	dw=pLeftOf->GetBarStyle(); 
 
	n = 0; 
	n = (dw&CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n; 
	n = (dw&CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n; 
	n = (dw&CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n; 
	n = (dw&CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n; 
	 
	// When we take the default parameters on rect, DockControlBar will dock 
	// each Toolbar on a seperate line. By calculating a rectangle, we 
	// are simulating a Toolbar being dragged to that location and docked. 
	m_pFrame->DockControlBar (pBar,n,&rect); 
} 
//**************************************************************************************** 
void CBCGFrameImpl::SetupToolbarMenu (CMenu& menu,  
									  const UINT uiViewUserToolbarCmdFirst, 
									  const UINT uiViewUserToolbarCmdLast) 
{ 
	//--------------------------------------------------------------- 
	// Replace toolbar dummy items to the user-defined toolbar names: 
	//--------------------------------------------------------------- 
	for (int i = 0; i < (int) menu.GetMenuItemCount ();) 
	{ 
		UINT uiCmd = menu.GetMenuItemID (i); 
 
		if (uiCmd >= uiViewUserToolbarCmdFirst &&  
			uiCmd <= uiViewUserToolbarCmdLast) 
		{ 
			//------------------------------------------------------------------- 
			// "User toolbar" item. First check that toolbar number 'x' is exist: 
			//------------------------------------------------------------------- 
			CBCGToolBar* pToolBar = GetUserBarByIndex (uiCmd - uiViewUserToolbarCmdFirst); 
			if (pToolBar != NULL) 
			{ 
				ASSERT_VALID (pToolBar); 
 
				//----------------------------------------------------------- 
				// Modify the current menu item text to the toolbar title and 
				// move next: 
				//----------------------------------------------------------- 
				CString strToolbarName; 
				pToolBar->GetWindowText (strToolbarName); 
 
				menu.ModifyMenu (i ++, MF_BYPOSITION | MF_STRING, uiCmd, strToolbarName); 
			} 
			else 
			{ 
				menu.DeleteMenu (i, MF_BYPOSITION); 
			} 
		} 
		else	// Not "user toolbar" item, move next 
		{ 
			i ++; 
		} 
	} 
} 
 
 
// Copyright (C) 1997,'98 by Joerg Koenig 
// All rights reserved 
// 
 
///////////////////////////////////////////////////////////////////////////// 
// helpers for docking  
///////////////////////////////////////////////////////////////////////////// 
 
 
// We need our own version of a dock bar, because the original 
// MFC implementation overlapps toolbars. CBCGToolBar don't want 
// such a overlapping, because this makes it impossible to draw 
// a real 3d border ... 
class CBCGToolDockBar : public CDockBar { 
	DECLARE_DYNAMIC(CBCGToolDockBar) 
 
	public: 
		// this is the one and only method of interest 
		virtual CSize	CalcFixedLayout(BOOL bStretch, BOOL bHorz); 
}; 
 
IMPLEMENT_DYNAMIC(CBCGToolDockBar, CDockBar); 
 
CSize CBCGToolDockBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) 
{ 
	ASSERT_VALID(this); 
 
	CSize sizeFixed = CControlBar::CalcFixedLayout(bStretch, bHorz); 
 
	// get max size 
	CSize sizeMax; 
	if (!m_rectLayout.IsRectEmpty()) 
		sizeMax = m_rectLayout.Size(); 
	else 
	{ 
		CRect rectFrame; 
		CFrameWnd* pFrame = GetParentFrame(); 
		pFrame->GetClientRect(&rectFrame); 
		sizeMax = rectFrame.Size(); 
	} 
 
	// prepare for layout 
	AFX_SIZEPARENTPARAMS layout; 
	layout.hDWP = m_bLayoutQuery ? 
		NULL : ::BeginDeferWindowPos(m_arrBars.GetSize()); 
	int cxBorder = afxData.cxBorder2;  
	int cyBorder = afxData.cyBorder2; 
 
	CPoint pt(-cxBorder, -cyBorder); 
	int nWidth = 0; 
 
	BOOL bWrapped = FALSE; 
	BOOL bFirstBar = TRUE; 
 
	// layout all the control bars 
	for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++) 
	{ 
		CControlBar* pBar = GetDockedControlBar(nPos); 
		void* pVoid = m_arrBars[nPos]; 
 
		if (pBar != NULL) 
		{ 
			if (pBar->IsKindOf (RUNTIME_CLASS(CBCGToolBar)) || 
				pBar->IsKindOf (RUNTIME_CLASS(CBCGSizingControlBar)) || 
				pBar->IsKindOf (RUNTIME_CLASS(CBCGDialogBar))) 
			{ 
				cxBorder = cyBorder = 0; 
			} 
			else 
			{ 
				cxBorder = afxData.cxBorder2; 
				cyBorder = afxData.cyBorder2; 
			} 
 
			if (pBar->IsVisible()) 
			{ 
				// get ideal rect for bar 
				DWORD dwMode = 0; 
				if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) && 
					(pBar->m_dwStyle & CBRS_FLOATING)) 
					dwMode |= LM_HORZ | LM_MRUWIDTH; 
				else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ) 
					dwMode |= LM_HORZ | LM_HORZDOCK; 
				else 
					dwMode |=  LM_VERTDOCK; 
 
				CSize sizeBar = pBar->CalcDynamicLayout(-1, dwMode); 
				BOOL bIsMenuBar = FALSE; 
 
				if (pBar->IsKindOf (RUNTIME_CLASS(CBCGMenuBar))) 
				{ 
					bIsMenuBar = TRUE; 
 
					if (dwMode & LM_HORZDOCK) 
					{ 
						sizeBar.cx = sizeMax.cx; 
					} 
					else if (dwMode & LM_VERTDOCK) 
					{ 
						sizeBar.cy = sizeMax.cy; 
					} 
				} 
 
				if (bFirstBar) 
				{ 
					if (dwMode & LM_HORZDOCK) 
					{ 
						pt.x = -cxBorder; 
					} 
					else if (dwMode & LM_VERTDOCK) 
					{ 
						pt.y = -cyBorder; 
					} 
				} 
 
				CRect rect(pt, sizeBar); 
 
				// get current rect for bar 
				CRect rectBar; 
				pBar->GetWindowRect(&rectBar); 
				ScreenToClient(&rectBar); 
 
				BOOL bMenuIsCutted = FALSE; 
 
				if (bHorz) 
				{ 
					// Offset Calculated Rect out to Actual 
					if (rectBar.left > rect.left && !m_bFloating) 
						rect.OffsetRect(rectBar.left - rect.left, 0); 
 
					// If ControlBar goes off the right, then right justify 
 
					if (rect.right > sizeMax.cx && !m_bFloating) 
					{ 
						int x = rect.Width() - cxBorder; 
						x = max(sizeMax.cx - x, pt.x); 
						rect.OffsetRect(x - rect.left, 0); 
 
						if (bIsMenuBar) 
						{ 
							bMenuIsCutted = TRUE; 
						} 
 
						if (rect.right > sizeMax.cx) 
						{ 
							rect.right = sizeMax.cx; 
						} 
					} 
 
					// If ControlBar has been wrapped, then left justify 
					if (bWrapped) 
					{ 
						bWrapped = FALSE; 
						rect.OffsetRect(-(rect.left + cxBorder), 0); 
					} 
					// If ControlBar is completely invisible, then wrap it 
					else if ((rect.left >= (sizeMax.cx - cxBorder) || bMenuIsCutted) && 
						(nPos > 0) && (m_arrBars[nPos - 1] != NULL)) 
					{ 
						m_arrBars.InsertAt(nPos, (CObject*)NULL); 
						pBar = NULL; pVoid = NULL; 
						bWrapped = TRUE; 
					} 
					if (!bWrapped) 
					{ 
						if (rect != rectBar) 
						{ 
							if (!m_bLayoutQuery && 
								!(pBar->m_dwStyle & CBRS_FLOATING)) 
							{ 
								pBar->m_pDockContext->m_rectMRUDockPos = rect; 
							} 
 
							AfxRepositionWindow(&layout, pBar->m_hWnd, &rect); 
						} 
						pt.x = rect.left + sizeBar.cx - cxBorder; 
						nWidth = max(nWidth, sizeBar.cy); 
					} 
				} 
				else 
				{ 
					// Offset Calculated Rect out to Actual 
					if (rectBar.top > rect.top && !m_bFloating) 
						rect.OffsetRect(0, rectBar.top - rect.top); 
 
					// If ControlBar goes off the bottom, then bottom justify 
					if (rect.bottom > sizeMax.cy && !m_bFloating) 
					{ 
						int y = rect.Height() - cyBorder; 
						y = max(sizeMax.cy - y, pt.y); 
						rect.OffsetRect(0, y - rect.top); 
 
						if (bIsMenuBar) 
						{ 
							bMenuIsCutted = TRUE; 
						} 
 
						if (rect.bottom > sizeMax.cy) 
						{ 
							rect.bottom = sizeMax.cy; 
						} 
					} 
 
					// If ControlBar has been wrapped, then top justify 
					if (bWrapped) 
					{ 
						bWrapped = FALSE; 
						rect.OffsetRect(0, -(rect.top + cyBorder)); 
					} 
					// If ControlBar is completely invisible, then wrap it 
					else if ((rect.top >= (sizeMax.cy - cyBorder) || bIsMenuBar) && 
						(nPos > 0) && (m_arrBars[nPos - 1] != NULL)) 
					{ 
						m_arrBars.InsertAt(nPos, (CObject*)NULL); 
						pBar = NULL; pVoid = NULL; 
						bWrapped = TRUE; 
					} 
 
					if (!bWrapped) 
					{ 
						if (rect != rectBar) 
						{ 
							if (!m_bLayoutQuery && 
								!(pBar->m_dwStyle & CBRS_FLOATING) && 
								pBar->m_pDockContext != NULL) 
							{ 
								pBar->m_pDockContext->m_rectMRUDockPos = rect; 
							} 
 
							AfxRepositionWindow(&layout, pBar->m_hWnd, &rect); 
						} 
						pt.y = rect.top + sizeBar.cy - cyBorder; 
						nWidth = max(nWidth, sizeBar.cx); 
					} 
				} 
 
				bFirstBar = FALSE; 
			} 
 
			if (!bWrapped) 
			{ 
				// handle any delay/show hide for the bar 
				pBar->RecalcDelayShow(&layout); 
			} 
		} 
 
		if (pBar == NULL && pVoid == NULL && nWidth != 0) 
		{ 
			// end of row because pBar == NULL 
			if (bHorz) 
			{ 
				pt.y += nWidth - cyBorder; 
				sizeFixed.cx = max(sizeFixed.cx, pt.x); 
				sizeFixed.cy = max(sizeFixed.cy, pt.y); 
				pt.x = -cxBorder; 
 
				sizeFixed.cy --;	// By Sven Ritter 
 
			} 
			else 
			{ 
				pt.x += nWidth - cxBorder; 
				sizeFixed.cx = max(sizeFixed.cx, pt.x); 
				sizeFixed.cy = max(sizeFixed.cy, pt.y); 
				pt.y = -cyBorder; 
 
				sizeFixed.cx --;	// By Sven Ritter 
			} 
			nWidth = 0; 
		} 
	} 
	if (!m_bLayoutQuery) 
	{ 
		// move and resize all the windows at once! 
		if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP)) 
			TRACE0("Warning: DeferWindowPos failed - low system resources.\n"); 
	} 
 
	// adjust size for borders on the dock bar itself 
	CRect rect; 
	rect.SetRectEmpty(); 
	CalcInsideRect(rect, bHorz); 
 
	if ((!bStretch || !bHorz) && sizeFixed.cx != 0) 
		sizeFixed.cx += -rect.right + rect.left; 
	if ((!bStretch || bHorz) && sizeFixed.cy != 0) 
		sizeFixed.cy += -rect.bottom + rect.top; 
 
	return sizeFixed; 
} 
 
// dwDockBarMap 
const DWORD dwDockBarMap[4][2] = 
{ 
	{ AFX_IDW_DOCKBAR_TOP,      CBRS_TOP    }, 
	{ AFX_IDW_DOCKBAR_BOTTOM,   CBRS_BOTTOM }, 
	{ AFX_IDW_DOCKBAR_LEFT,     CBRS_LEFT   }, 
	{ AFX_IDW_DOCKBAR_RIGHT,    CBRS_RIGHT  }, 
}; 
 
 
// Unfortunataly a simple rewrite of CFrameWnd's EnableDocking() is not possible, 
// because we have not enough permissions to access some data in this class. 
// That's why we call CFrameWnd::EnableDocking() first and exchange all occurencies 
// of CDockBar objects with our own version of a dock bar. 
void CBCGFrameImpl::FrameEnableDocking(CFrameWnd * pFrame, DWORD dwDockStyle)  
{ 
	ASSERT_VALID(pFrame); 
 
	// must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only 
	ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0); 
 
	pFrame->EnableDocking(dwDockStyle); 
 
	for (int i = 0; i < 4; i++)  
	{ 
		if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)  
		{ 
			CDockBar* pDock = (CDockBar*)pFrame->GetControlBar(dwDockBarMap[i][0]); 
			 
			// make sure the dock bar is of correct type 
			if( pDock == 0 || ! pDock->IsKindOf(RUNTIME_CLASS(CBCGToolDockBar)) ) { 
				BOOL bNeedDelete = ! pDock->m_bAutoDelete; 
				pDock->m_pDockSite->RemoveControlBar(pDock); 
				pDock->m_pDockSite = 0;	// avoid problems in destroying the dockbar 
				pDock->DestroyWindow(); 
				if( bNeedDelete ) 
					delete pDock; 
				pDock = 0; 
			} 
 
			if( pDock == 0 ) { 
				pDock = new CBCGToolDockBar; 
				if (!pDock->Create(pFrame, 
					WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE | 
						dwDockBarMap[i][1], dwDockBarMap[i][0])) { 
					AfxThrowResourceException(); 
				} 
			} 
		} 
	} 
} 
//******************************************************************************** 
BOOL CBCGFrameImpl::OnMenuChar (UINT nChar) 
{ 
	if (m_pMenuBar != NULL && 
		(m_pMenuBar->GetStyle () & WS_VISIBLE) && 
		m_pMenuBar->TranslateChar (nChar)) 
	{ 
		return TRUE; 
	} 
 
	for (POSITION posTlb = gAllToolbars.GetHeadPosition (); posTlb != NULL;) 
	{ 
		CBCGToolBar* pToolBar = (CBCGToolBar*) gAllToolbars.GetNext (posTlb); 
		ASSERT (pToolBar != NULL); 
 
		if (CWnd::FromHandlePermanent (pToolBar->m_hWnd) != NULL && 
			pToolBar != m_pMenuBar && 
			(pToolBar->GetStyle () & WS_VISIBLE) && 
			pToolBar->GetTopLevelFrame () == m_pFrame && 
			pToolBar->TranslateChar (nChar)) 
		{ 
			return TRUE; 
		} 
	} 
 
	return FALSE; 
}