www.pudn.com > clking_src.rar > GuiDockContext.cpp


//-----------------------------------------------------------------------// 
// This is a part of the GuiLib MFC Extention.							 //	 
// Autor  :  Francisco Campos											 // 
// (C) 2002 Francisco Campos  All rights reserved     // 
// This code is provided "as is", with absolutely no warranty expressed  // 
// or implied. Any use is at your own risk.								 //		 
// You must obtain the author's consent before you can include this code // 
// in a software library.												 // 
// If the source code in  this file is used in any application			 // 
// then acknowledgement must be made to the author of this program		 //	 
// fcampos@tutopia.com													 // 
//-----------------------------------------------------------------------// 
 
#include "stdafx.h" 
#include "GuiDockContext.h" 
#include "GuiToolBarWnd.h" 
#include "MenuBar.h" 
#include "GuiControlBar.h" 
#define _AfxGetDlgCtrlID(hWnd)          ((UINT)(WORD)::GetDlgCtrlID(hWnd)) 
#ifdef AFX_CORE3_SEG 
#pragma code_seg(AFX_CORE3_SEG) 
#endif 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define new DEBUG_NEW 
 
#define HORZF(dw) (dw & CBRS_ORIENT_HORZ) 
#define VERTF(dw) (dw & CBRS_ORIENT_VERT) 
#define CX_BORDER   1 
#define CY_BORDER   1 
 
 
AFX_STATIC void AFXAPI _AfxAdjustRectangle(CRect& rect, CPoint pt) 
{ 
	int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) : 
					(pt.x > rect.right) ? (pt.x - rect.right) : 0; 
	int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) : 
					(pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0; 
	rect.OffsetRect(nXOffset, nYOffset); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CGuiDockContext 
 
CGuiDockContext::CGuiDockContext(CControlBar* pBar):CDockContext(pBar) 
{ 
	bFirstClic=TRUE; 
	bSecondClic=TRUE; 
} 
 
CGuiDockContext::~CGuiDockContext() 
{ 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CGuiDockContext Drag Operations 
 
void CGuiDockContext::StartDrag(CPoint pt) 
{ 
	ASSERT_VALID(m_pBar); 
	m_bDragging = TRUE; 
 
	InitLoop(); 
 
	// GetWindowRect returns screen coordinates(not mirrored), 
	// so if the desktop is mirrored then turn off mirroring 
	// for the desktop dc so that we get correct focus rect drawn. 
	// This layout change should be remembered, just in case ... 
 
	if (m_pDC->GetLayout() & LAYOUT_RTL) 
		m_pDC->SetLayout(LAYOUT_LTR); 
 
	if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) 
	{ 
		// get true bar size (including borders) 
		CRect rect; 
		m_pBar->GetWindowRect(rect); 
		m_ptLast = pt; 
		AdjustWindowForFloat(rect); 
		CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK); 
		CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK); 
		CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH); 
 
		m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); 
		m_rectDragVert = CRect(rect.TopLeft(), sizeVert); 
 
		// calculate frame dragging rectangle 
		m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat); 
		m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat); 
 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
 
//		m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
//		m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
	} 
	else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED) 
	{ 
		// get true bar size (including borders) 
		CRect rect; 
		m_pBar->GetWindowRect(rect); 
		AdjustWindowForFloat(rect); 
		m_ptLast = pt; 
		CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK); 
		CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK); 
 
		// calculate frame dragging rectangle 
		m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); 
		m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert); 
 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
//		m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
//		m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
	} 
	else 
	{ 
		// get true bar size (including borders) 
		CRect rect; 
		m_pBar->GetWindowRect(rect); 
		AdjustWindowForFloat(rect); 
		m_ptLast = pt; 
		BOOL bHorz = HORZF(m_dwStyle); 
		DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK; 
		CSize size = m_pBar->CalcDynamicLayout(-1, dwMode); 
 
		// calculate inverted dragging rect 
		if (bHorz) 
		{ 
			m_rectDragHorz = rect; 
			m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size); 
		} 
		else // vertical orientation 
		{ 
			m_rectDragVert = rect; 
			m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size); 
		} 
 
		// calculate frame dragging rectangle 
		m_rectFrameDragHorz = m_rectDragHorz; 
		m_rectFrameDragVert = m_rectDragVert; 
 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
		CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
//		m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
//		m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
	} 
 
	// adjust rectangles so that point is inside 
	_AfxAdjustRectangle(m_rectDragHorz, pt); 
	_AfxAdjustRectangle(m_rectDragVert, pt); 
	_AfxAdjustRectangle(m_rectFrameDragHorz, pt); 
	_AfxAdjustRectangle(m_rectFrameDragVert, pt); 
 
	// initialize tracking state and enter tracking loop 
	m_dwOverDockStyle = CanDock(); 
	Move(pt);   // call it here to handle special keys 
	Track(); 
} 
 
void CGuiDockContext::AdjustWindowForFloat(CRect& rect) 
{ 
	if( m_pBar->IsFloating()) 
	{ 
		rect.top+=(GetSystemMetrics(SM_CYCAPTION)); 
		rect.bottom-=(GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION))*2; 
	} 
} 
 
void CGuiDockContext::Move(CPoint pt) 
{ 
	CPoint ptOffset = pt - m_ptLast; 
 
	// offset all drag rects to new position 
	m_rectDragHorz.OffsetRect(ptOffset); 
	m_rectFrameDragHorz.OffsetRect(ptOffset); 
	m_rectDragVert.OffsetRect(ptOffset); 
	m_rectFrameDragVert.OffsetRect(ptOffset); 
	m_ptLast = pt; 
 
	// if control key is down don't dock 
	m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock(); 
 
	// update feedback 
	DrawFocusRect(); 
} 
 
void CGuiDockContext::OnKey(int nChar, BOOL bDown) 
{ 
	if (nChar == VK_CONTROL) 
		UpdateState(&m_bForceFrame, bDown); 
	if (nChar == VK_SHIFT) 
		UpdateState(&m_bFlip, bDown); 
} 
 
void CGuiDockContext::EndDrag() 
{ 
	CancelLoop(); 
 
	if (m_dwOverDockStyle != 0) 
	{ 
		CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle); 
		ASSERT(pDockBar != NULL); 
 
		CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ? 
			m_rectDragVert : m_rectDragHorz; 
 
		UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd); 
		if (uID >= AFX_IDW_DOCKBAR_TOP && 
			uID <= AFX_IDW_DOCKBAR_BOTTOM) 
		{ 
					 
			m_uMRUDockID = uID; 
			m_rectMRUDockPos = rect; 
			pDockBar->ScreenToClient(&m_rectMRUDockPos); 
		} 
	 
		// dock it at the specified position, RecalcLayout will snap 
		m_pDockSite->DockControlBar(m_pBar, pDockBar, &rect); 
		m_pDockSite->RecalcLayout(); 
	} 
	else if ((m_dwStyle & CBRS_SIZE_DYNAMIC) || (HORZF(m_dwStyle) && !m_bFlip) || 
			(VERTF(m_dwStyle) && m_bFlip)) 
	{ 
		m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI); 
		m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft(); 
		m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle); 
	} 
	else // vertical float 
	{ 
		m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (m_dwDockStyle & CBRS_FLOAT_MULTI); 
		m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft(); 
		m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CGuiDockContext Resize Operations 
 
#define m_rectRequestedSize     m_rectDragHorz 
#define m_rectActualSize        m_rectDragVert 
#define m_rectActualFrameSize   m_rectFrameDragHorz 
#define m_rectFrameBorders      m_rectFrameDragVert 
 
void CGuiDockContext::StartResize(int nHitTest, CPoint pt) 
{ 
	ASSERT_VALID(m_pBar); 
	ASSERT(m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC); 
	m_bDragging = FALSE; 
 
	InitLoop(); 
 
	// GetWindowRect returns screen coordinates(not mirrored) 
	// So if the desktop is mirrored then turn off mirroring 
	// for the desktop dc so that we draw correct focus rect 
 
	if (m_pDC->GetLayout() & LAYOUT_RTL) 
		m_pDC->SetLayout(LAYOUT_LTR); 
 
	// get true bar size (including borders) 
	CRect rect; 
	m_pBar->GetWindowRect(rect); 
	m_ptLast = pt; 
	m_nHitTest = nHitTest; 
 
	CSize size = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH); 
	m_rectRequestedSize = CRect(rect.TopLeft(), size); 
	m_rectActualSize = CRect(rect.TopLeft(), size); 
	m_rectActualFrameSize = CRect(rect.TopLeft(), size); 
 
	// calculate frame rectangle 
	CMiniFrameWnd::CalcBorders(&m_rectActualFrameSize); 
//	m_rectActualFrameSize.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
 
	m_rectFrameBorders = CRect(CPoint(0,0), 
		m_rectActualFrameSize.Size() - m_rectActualSize.Size()); 
 
	// initialize tracking state and enter tracking loop 
	m_dwOverDockStyle = 0; 
	Stretch(pt);   // call it here to handle special keys 
	Track(); 
} 
 
void CGuiDockContext::Stretch(CPoint pt) 
{ 
	CPoint ptOffset = pt - m_ptLast; 
 
	// offset all drag rects to new position 
	int nLength = 0; 
	DWORD dwMode = LM_HORZ; 
	if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT) 
	{ 
		if (m_nHitTest == HTLEFT) 
			m_rectRequestedSize.left += ptOffset.x; 
		else 
			m_rectRequestedSize.right += ptOffset.x; 
		nLength = m_rectRequestedSize.Width(); 
	} 
	else 
	{ 
		dwMode |= LM_LENGTHY; 
		if (m_nHitTest == HTTOP) 
			m_rectRequestedSize.top += ptOffset.y; 
		else 
			m_rectRequestedSize.bottom += ptOffset.y; 
		nLength = m_rectRequestedSize.Height(); 
	} 
	nLength = (nLength >= 0) ? nLength : 0; 
 
	CSize size = m_pBar->CalcDynamicLayout(nLength, dwMode); 
 
	CRect rectDesk; 
	HWND hWndDesk = ::GetDesktopWindow(); 
	::GetWindowRect(hWndDesk, &rectDesk); 
	CRect rectTemp = m_rectActualFrameSize; 
 
	if (m_nHitTest == HTLEFT || m_nHitTest == HTTOP) 
	{ 
		rectTemp.left = rectTemp.right - 
			(size.cx + m_rectFrameBorders.Width()); 
		rectTemp.top = rectTemp.bottom - 
			(size.cy + m_rectFrameBorders.Height()); 
		CRect rect; 
		if (rect.IntersectRect(rectDesk, rectTemp)) 
		{ 
			m_rectActualSize.left = m_rectActualSize.right - size.cx; 
			m_rectActualSize.top = m_rectActualSize.bottom - size.cy; 
			m_rectActualFrameSize.left = rectTemp.left; 
			m_rectActualFrameSize.top = rectTemp.top; 
		} 
	} 
	else 
	{ 
		rectTemp.right = rectTemp.left + 
			(size.cx + m_rectFrameBorders.Width()); 
		rectTemp.bottom = rectTemp.top + 
			(size.cy + m_rectFrameBorders.Height()); 
		CRect rect; 
		if (rect.IntersectRect(rectDesk, rectTemp)) 
		{ 
			m_rectActualSize.right = m_rectActualSize.left + size.cx; 
			m_rectActualSize.bottom = m_rectActualSize.top + size.cy; 
			m_rectActualFrameSize.right = rectTemp.right; 
			m_rectActualFrameSize.bottom = rectTemp.bottom; 
		} 
	} 
	m_ptLast = pt; 
 
	// update feedback 
	DrawFocusRect(); 
} 
 
void CGuiDockContext::EndResize() 
{ 
	CancelLoop(); 
 
	m_pBar->CalcDynamicLayout(m_rectActualSize.Width(), LM_HORZ | LM_COMMIT); 
	m_pDockSite->FloatControlBar(m_pBar, m_rectActualFrameSize.TopLeft(), 
		CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI) | CBRS_SIZE_DYNAMIC); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CGuiDockContext Double Click Operations 
 
void CGuiDockContext::ToggleDocking() 
{ 
	if (m_pBar->IsFloating()) 
	{ 
		// Dock it only if is allowed to be docked 
		if (m_pBar->m_dwDockStyle & CBRS_ALIGN_ANY) 
		{ 
			ASSERT((m_uMRUDockID >= AFX_IDW_DOCKBAR_TOP && 
				m_uMRUDockID <= AFX_IDW_DOCKBAR_BOTTOM) || 
				m_uMRUDockID == 0); 
					 
			CRect rect = m_rectMRUDockPos; 
			CDockBar* pDockBar = NULL; 
			if (m_uMRUDockID != 0) 
			{ 
				pDockBar = (CDockBar*)m_pDockSite->GetControlBar(m_uMRUDockID); 
				pDockBar->ClientToScreen(&rect); 
			} 
 
			// dock it at the specified position, RecalcLayout will snap 
			m_pDockSite->ReDockControlBar(m_pBar, pDockBar, &rect); 
			m_pDockSite->RecalcLayout(); 
		} 
	} 
	else 
	{ 
		CPoint ptFloat = m_ptMRUFloatPos; 
		if (ptFloat.x < 0 || ptFloat.y < 0) 
		{ 
			ptFloat = m_rectMRUDockPos.TopLeft(); 
			m_pBar->GetParent()->ClientToScreen(&ptFloat); 
		} 
		m_pDockSite->FloatControlBar(m_pBar, ptFloat, m_dwMRUFloatStyle); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CGuiDockContext Operations 
 
void CGuiDockContext::InitLoop() 
{ 
	// handle pending WM_PAINT messages 
	MSG msg; 
	while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE)) 
	{ 
		if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT)) 
			return; 
		DispatchMessage(&msg); 
	} 
 
	// get styles from bar 
	m_dwDockStyle = m_pBar->m_dwDockStyle; 
	m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY; 
	ASSERT(m_dwStyle != 0); 
 
	// initialize state 
	m_rectLast.SetRectEmpty(); 
	m_sizeLast.cx = m_sizeLast.cy = 0; 
	m_bForceFrame = m_bFlip = m_bDitherLast = FALSE; 
 
	// lock window update while dragging 
	ASSERT(m_pDC == NULL); 
	CWnd* pWnd = CWnd::GetDesktopWindow(); 
	if (pWnd->LockWindowUpdate()) 
		m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE); 
	else 
		m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE); 
	ASSERT(m_pDC != NULL); 
} 
 
void CGuiDockContext::CancelLoop() 
{ 
	DrawFocusRect(TRUE);    // gets rid of focus rect 
	ReleaseCapture(); 
 
	CWnd* pWnd = CWnd::GetDesktopWindow(); 
	pWnd->UnlockWindowUpdate(); 
	if (m_pDC != NULL) 
	{ 
		pWnd->ReleaseDC(m_pDC); 
		m_pDC = NULL; 
	} 
	bFirstClic=TRUE; 
	bSecondClic=TRUE; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// Implementation 
 
void CGuiDockContext::DrawFocusRect(BOOL bRemoveRect) 
{ 
	ASSERT(m_pDC != NULL); 
 
	// default to thin frame 
	CSize size(CX_BORDER, CY_BORDER); 
 
	// determine new rect and size 
	CRect rect; 
	CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH)); 
	CBrush* pDitherBrush = CDC::GetHalftoneBrush(); 
	CBrush* pBrush = pWhiteBrush; 
 
	if (HORZF(m_dwOverDockStyle)) 
		rect = m_rectDragHorz; 
	else if (VERTF(m_dwOverDockStyle)) 
		rect = m_rectDragVert; 
	else 
	{ 
		// use thick frame instead 
		size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER; 
		size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER; 
		if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip)) 
			rect = m_rectFrameDragHorz; 
		else 
			rect = m_rectFrameDragVert; 
		pBrush = pDitherBrush; 
	} 
	if (bRemoveRect) 
		size.cx = size.cy = 0; 
 
/*	if (afxData.bWin4 && 
		(HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle))) 
	{ 
		// looks better one pixel in (makes the bar look pushed down) 
		rect.InflateRect(-CX_BORDER, -CY_BORDER); 
	} 
*/ 
	// draw it and remember last size 
	 
	if (bFirstClic==TRUE) 
	{ 
		bFirstClic=FALSE; 
	} 
	else{ 
		if (bSecondClic==TRUE) 
		{ 
		  m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast, 
			pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush); 
		  m_bDitherLast = (pBrush == pDitherBrush); 
		   m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast, 
			pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush); 
		  bSecondClic=FALSE; 
		} 
		else 
		{ 
			m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast, 
			pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush); 
			m_rectLast = rect; 
			m_sizeLast = size; 
			m_bDitherLast = (pBrush == pDitherBrush); 
		} 
	} 
	 
} 
 
void CGuiDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue) 
{ 
	if (*pFlag != bNewValue) 
	{ 
		*pFlag = bNewValue; 
		m_bFlip = (HORZF(m_dwDockStyle) && VERTF(m_dwDockStyle) && m_bFlip); // shift key 
		m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock(); 
		DrawFocusRect(); 
	} 
} 
 
DWORD CGuiDockContext::CanDock() 
{ 
	BOOL bStyleHorz; 
	DWORD dwDock = 0; // Dock Canidate 
	DWORD dwCurr = 0; // Current Orientation 
 
	// let's check for something in our current orientation first 
	// then if the shift key is not forcing our orientation then 
	// check for horizontal or vertical orientations as long 
	// as we are close enough 
	ASSERT(m_dwStyle != 0); 
 
	bStyleHorz = HORZF(m_dwStyle); 
	bStyleHorz = m_bFlip ? !bStyleHorz : bStyleHorz; 
 
	if (bStyleHorz && HORZF(m_dwDockStyle)) 
		dwDock = CanDock(m_rectDragHorz, 
									  m_dwDockStyle & ~CBRS_ORIENT_VERT); 
	else if (VERTF(m_dwDockStyle)) 
		dwDock = CanDock(m_rectDragVert, 
									  m_dwDockStyle & ~CBRS_ORIENT_HORZ); 
 
	if (!m_bFlip) 
	{ 
		if (dwDock == 0 && HORZF(m_dwDockStyle)) 
		{ 
			dwCurr = CanDock(m_rectDragVert, 
										  m_dwDockStyle & ~CBRS_ORIENT_VERT); 
			dwDock = CanDock(m_rectDragHorz, 
										  m_dwDockStyle & ~CBRS_ORIENT_VERT); 
			dwDock = (dwDock == dwCurr) ? dwDock : 0; 
		} 
		if (dwDock == 0 && VERTF(m_dwDockStyle)) 
		{ 
			dwCurr = CanDock(m_rectDragHorz, 
										  m_dwDockStyle & ~CBRS_ORIENT_HORZ); 
			dwDock = CanDock(m_rectDragVert, 
										  m_dwDockStyle & ~CBRS_ORIENT_HORZ); 
			dwDock = (dwDock == dwCurr) ? dwDock : 0; 
		} 
	} 
 
	return dwDock; 
} 
 
 
DWORD CGuiDockContext::CanDock(CRect rect, DWORD dwDockStyle, CDockBar** ppDockBar) 
{ 
	// dwDockStyle -- allowable styles of bar 
	// don't allow to dock to floating unless multi is specified 
	BOOL bTipoToolBar=m_pBar->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd)) || 
		              m_pBar->IsKindOf(RUNTIME_CLASS( CMenuBar)); 
	dwDockStyle &= CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI; 
	if (ppDockBar != NULL) 
		*ppDockBar = NULL; 
	POSITION pos = m_pDockSite->m_listControlBars.GetHeadPosition(); 
	while (pos != NULL) 
	{ 
		CDockBar* pDockBar = (CDockBar*)m_pDockSite->m_listControlBars.GetNext(pos); 
		if (pDockBar->IsDockBar() && pDockBar->IsWindowVisible() && 
			(pDockBar->m_dwStyle & dwDockStyle & CBRS_ALIGN_ANY) && 
			(!pDockBar->m_bFloating || 
				(dwDockStyle & pDockBar->m_dwStyle & CBRS_FLOAT_MULTI))) 
		{ 
		 
				int nSize=pDockBar->m_arrBars.GetSize(); 
				for (int i=0;i GetDlgCtrlID(); 
					CControlBar* pBar; 
					 pBar = (CControlBar*) pDockBar->m_arrBars[i]; 
					 if (HIWORD(pBar) == 0) continue; // placeholder 
					 if (!pBar->IsVisible()) continue; 
					 CRect rectBar; 
					 pBar->GetWindowRect(&rectBar); 
					 if (rectBar.Width() == 0) 
						rectBar.right++; 
					 if (rectBar.Height() == 0) 
							rectBar.bottom++; 
					 CRect rectBar1; 
					 pDockBar->GetWindowRect(&rectBar1); 
					 if (dwDockStyle==CBRS_ORIENT_VERT) 
					 { 
						 if (m_nDockBarID==AFX_IDW_DOCKBAR_LEFT) 
					 		rectBar1.right=rectBar1.left+10; 
						 if(m_nDockBarID==AFX_IDW_DOCKBAR_RIGHT) 
							 rectBar1.left=rectBar1.right-10; 
					 } 
					 else 
					 { 
 
						if (m_nDockBarID==AFX_IDW_DOCKBAR_BOTTOM) 
							rectBar1.top=rectBar1.bottom-10; 
						if (m_nDockBarID==AFX_IDW_DOCKBAR_TOP) 
							rectBar1.bottom=rectBar1.top+10; 
						 
					 } 
					 if (rectBar1.IntersectRect(rectBar1, rect)) 
					 { 
						if (ppDockBar != NULL) 
							 
							*ppDockBar = pDockBar; 
						 
						return pDockBar->m_dwStyle & dwDockStyle; 
					 } 
			 
 
					//*********************************************** 
					if (rectBar.IntersectRect(rectBar, rect)) 
					{ 
							if (bTipoToolBar) 
							{ 
								if (pBar->IsKindOf(RUNTIME_CLASS( CGuiControlBar))) 
									return 0; 
							} 
							if (ppDockBar != NULL) 
								*ppDockBar = pDockBar; 
							return pDockBar->m_dwStyle & dwDockStyle; 
							 
						  
							 
					} 
					  
				}//fin del for 
							 
		 
			CRect rectBar; 
			pDockBar->GetWindowRect(&rectBar); 
			if (rectBar.Width() == 0) 
				rectBar.right++; 
			if (rectBar.Height() == 0) 
				rectBar.bottom++; 
			if (rectBar.IntersectRect(rectBar, rect)) 
			{ 
				if (ppDockBar != NULL) 
					*ppDockBar = pDockBar; 
				return pDockBar->m_dwStyle & dwDockStyle; 
			} 
		} 
	} 
	return 0; 
} 
 
//********************************************* 
// return 0 no acepta el docking 
//        1 lo acepta 
//        2 continue 
int  CGuiDockContext::VerLeft(int i,int nSize,CDockBar* pDockBar,CControlBar* pBar) 
{ 
	BOOL bTipoToolBar=m_pBar->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd)); 
	//i--; 
	if (i+1 < nSize) 
	{ 
		CControlBar* pBartemp; 
 		pBartemp = (CControlBar*) pDockBar->m_arrBars[i+1]; 
		if (HIWORD(pBartemp) == 0) return 2; // placeholder 
		if (!pBartemp->IsVisible()) return 2; 
		if (bTipoToolBar) 
				if (!pBartemp->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd))) 
					return 0;				 
	} 
	if (i > 0) 
	{ 
		CControlBar* pBartemp; 
		pBartemp = (CControlBar*) pDockBar->m_arrBars[i-1]; 
		if (HIWORD(pBartemp) == 0) return 2; // placeholder 
		if (!pBartemp->IsVisible()) return 2; 
		if (bTipoToolBar) 
				if (!pBartemp->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd))) 
					return 0;				 
	} 
 
	return 1; 
 
} 
 
//********************************************* 
// return 0 no acepta el docking 
//        1 lo acepta 
//        2 continue 
 
int  CGuiDockContext::VerRight(int i,int nSize,CDockBar* pDockBar,CControlBar* pBar) 
 
{ 
	BOOL bTipoToolBar=m_pBar->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd)); 
	//i--; 
	if (i==0) 
	{ 
		CControlBar* pBartemp; 
		pBartemp = (CControlBar*) pDockBar->m_arrBars[i+1]; 
		if (HIWORD(pBartemp) == 0) return 2; // placeholder 
		if (!pBartemp->IsVisible()) return 2; 
		if (bTipoToolBar) 
				if (!pBartemp->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd))) 
					return 0;				 
	} 
	if (i > 0) 
	{ 
			CControlBar* pBartemp; 
			pBartemp = (CControlBar*) pDockBar->m_arrBars[i-1]; 
			if (HIWORD(pBartemp) == 0) return 2; // placeholder 
			if (!pBartemp->IsVisible()) return 2; 
			if (bTipoToolBar) 
				if (!pBartemp->IsKindOf(RUNTIME_CLASS( CGuiToolBarWnd))) 
					return 0;				 
	 
	} 
	return 1; 
} 
 
CDockBar* CGuiDockContext::GetDockBar(DWORD dwOverDockStyle) 
{ 
	DWORD dw = 0; 
	CDockBar* pBar; 
	if (HORZF(dwOverDockStyle)) 
	{ 
		dw = CanDock(m_rectDragHorz, 
			dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar); 
		ASSERT(dw != 0); 
		ASSERT(pBar != NULL); 
		return pBar; 
	} 
	if (VERTF(dwOverDockStyle)) 
	{ 
		dw =CanDock(m_rectDragVert, 
			dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar); 
		ASSERT(dw != 0); 
		ASSERT(pBar != NULL); 
		return pBar; 
	} 
	return NULL; 
} 
 
BOOL CGuiDockContext::Track() 
{ 
	// don't handle if capture already set 
	if (::GetCapture() != NULL) 
		return FALSE; 
 
	// set capture to the window which received this message 
	m_pBar->SetCapture(); 
	ASSERT(m_pBar == CWnd::GetCapture()); 
 
	// get messages until capture lost or cancelled/accepted 
	while (CWnd::GetCapture() == m_pBar) 
	{ 
		MSG msg; 
		if (!::GetMessage(&msg, NULL, 0, 0)) 
		{ 
			AfxPostQuitMessage(msg.wParam); 
			break; 
		} 
 
		switch (msg.message) 
		{ 
		case WM_LBUTTONUP: 
			if (m_bDragging) 
				EndDrag(); 
			else 
				EndResize(); 
			return TRUE; 
		case WM_MOUSEMOVE: 
			if (m_bDragging) 
				Move(msg.pt); 
			else 
				Stretch(msg.pt); 
			break; 
		case WM_KEYUP: 
			if (m_bDragging) 
				OnKey((int)msg.wParam, FALSE); 
			break; 
		case WM_KEYDOWN: 
			if (m_bDragging) 
				OnKey((int)msg.wParam, TRUE); 
			if (msg.wParam == VK_ESCAPE) 
			{ 
				CancelLoop(); 
				return FALSE; 
			} 
			break; 
		case WM_RBUTTONDOWN: 
			CancelLoop(); 
			return FALSE; 
 
		// just dispatch rest of the messages 
		default: 
			DispatchMessage(&msg); 
			break; 
		} 
	} 
 
	CancelLoop(); 
 
	return FALSE; 
}