// XTPDockContext.cpp : implementation of the CXTPDockContext class. // // This file is a part of the XTREME COMMANDBARS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPHookManager.h" #include "XTPCommandBarsDefines.h" #include "XTPDockContext.h" #include "XTPCommandBar.h" #include "XTPToolBar.h" #include "XTPCommandBars.h" #include "XTPMouseManager.h" #include "XTPDockBar.h" #include "XTPDialogBar.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif void CXTPDockContext::AdjustRectangle(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); } CXTPDockContext::CXTPDockContext(CXTPToolBar* pBar) { m_pBar = pBar; m_uMRUDockPosition = xtpBarTop; m_rectMRUDockPos.SetRectEmpty(); m_ptMRUFloatPos.y = m_ptMRUFloatPos.x = 0; m_nHitTest = 0; } CXTPDockContext::~CXTPDockContext() { } void CXTPDockContext::StartDrag(CPoint pt) { m_nHitTest = HTCLIENT; CRect rectMRUDockPos = m_rectMRUDockPos; XTPBarPosition uMRUDockPosition = m_uMRUDockPosition; BOOL bFloating = m_pBar->m_barPosition == xtpBarFloating; CXTPWindowRect rect(m_pBar); m_ptLast = pt; AdjustRectangle(rect, pt); m_rectDragFrame = m_rectDragDock = rect; SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL)); XTPMouseManager()->LockMouseMove(); Track(); XTPMouseManager()->UnlockMouseMove(); if (m_pBar->m_barPosition == xtpBarFloating) { m_ptMRUFloatPos = m_rectDragFrame.TopLeft(); if (!bFloating) { m_rectMRUDockPos = rectMRUDockPos; m_uMRUDockPosition = uMRUDockPosition; } } } void CXTPDockContext::StartResize(int nHitTest, CPoint pt) { m_nHitTest = nHitTest; m_ptLast = pt; m_pBar->GetWindowRect(m_rectDragFrame); Track(); m_pBar->GetWindowRect(m_rectDragFrame); if (m_pBar->m_barPosition == xtpBarFloating) m_ptMRUFloatPos = m_rectDragFrame.TopLeft(); m_pBar->m_nMRUWidth = m_rectDragFrame.Width(); } void CXTPDockContext::Track() { // don't handle if capture already set if (::GetCapture() != NULL) return; // set capture to the window which received this message m_pBar->SetCapture(); ASSERT(m_pBar == CWnd::GetCapture()); CXTPCommandBars* pCommandBars = m_pBar->GetCommandBars(); ASSERT(pCommandBars); if (!pCommandBars) return; CPoint pt(0, 0); // get messages until capture lost or cancelled/accepted while (CWnd::GetCapture() == m_pBar) { MSG msg; if (!::GetMessage(&msg, NULL, 0, 0)) { AfxPostQuitMessage((int)msg.wParam); break; } if (msg.message == WM_LBUTTONUP) break; else if (msg.message == WM_MOUSEMOVE && pt != msg.pt) { pt = msg.pt; if (m_nHitTest == HTCLIENT) Move(msg.pt); else if (m_pBar->IsDialogBar()) Resize(msg.pt); else Stretch(msg.pt); } else if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) { break; } } else DispatchMessage(&msg); pCommandBars->IdleRecalcLayout(); } ReleaseCapture(); pCommandBars->GetCommandBarsOptions()->bDirtyState = TRUE; } void CXTPDockContext::EnsureVisible(CRect& rectDragFrame) { CRect rcWork = XTPMultiMonitor()->GetWorkArea(); int nGap = 10; if (rcWork.bottom - rectDragFrame.top < nGap) { rectDragFrame.OffsetRect(0, rcWork.bottom - rectDragFrame.top - nGap); } if (rectDragFrame.bottom - rcWork.top < nGap) { rectDragFrame.OffsetRect(0, rcWork.top - rectDragFrame.bottom + nGap); } if (rcWork.right - rectDragFrame.left < nGap) { rectDragFrame.OffsetRect(rcWork.right - rectDragFrame.left - nGap, 0); } if (rectDragFrame.right - rcWork.left < nGap) { rectDragFrame.OffsetRect(rcWork.left - rectDragFrame.right + nGap, 0); } } void CXTPDockContext::Move(CPoint pt) { CPoint ptOffset = pt - m_ptLast; CXTPCommandBars* pCommandBars = m_pBar->GetCommandBars(); ASSERT(pCommandBars); if (!pCommandBars) return; m_rectDragFrame.OffsetRect(ptOffset); m_rectDragDock.OffsetRect(ptOffset); DWORD dwFlags = m_pBar->GetFlags(); BOOL bDocked = FALSE; CXTPDockBar* pDockBar = pCommandBars->CanDock(pt, m_pBar->m_pDockBar); if (pDockBar) { XTPBarPosition position = pDockBar->GetPosition(); if ((position == xtpBarTop && dwFlags & xtpFlagAlignTop) || (position == xtpBarLeft && dwFlags & xtpFlagAlignLeft) || (position == xtpBarRight && dwFlags & xtpFlagAlignRight) || (position == xtpBarBottom && dwFlags & xtpFlagAlignBottom)) { CXTPDockBar* pOldDockBar = m_pBar->m_pDockBar; pCommandBars->DockCommandBar(m_pBar, &m_rectDragDock, pDockBar); if (pDockBar != pOldDockBar || m_pBar->GetPosition() == xtpBarFloating) { pCommandBars->RecalcFrameLayout(); m_pBar->GetWindowRect(m_rectDragDock); } bDocked = TRUE; } } if (!bDocked && (dwFlags & xtpFlagFloating)) { if (m_pBar->GetPosition() != xtpBarFloating) { pCommandBars->FloatCommandBar(m_pBar); CSize sz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT); m_rectDragFrame = CRect(m_rectDragFrame.TopLeft(), sz); AdjustRectangle(m_rectDragFrame, pt); } EnsureVisible(m_rectDragFrame); m_pBar->MoveWindow(m_rectDragFrame); } m_ptLast = pt; } void CXTPDockContext::Resize(CPoint pt) { CPoint ptOffset = pt - m_ptLast; ASSERT(m_pBar->IsDialogBar()); if (m_nHitTest == HTLEFT || m_nHitTest == HTTOPLEFT || m_nHitTest == HTBOTTOMLEFT) m_rectDragFrame.left += ptOffset.x; if (m_nHitTest == HTRIGHT || m_nHitTest == HTTOPRIGHT || m_nHitTest == HTBOTTOMRIGHT) m_rectDragFrame.right += ptOffset.x; if (m_nHitTest == HTTOP || m_nHitTest == HTTOPRIGHT || m_nHitTest == HTTOPLEFT) m_rectDragFrame.top += ptOffset.y; if (m_nHitTest == HTBOTTOM || m_nHitTest == HTBOTTOMRIGHT || m_nHitTest == HTBOTTOMLEFT) m_rectDragFrame.bottom += ptOffset.y; CRect rectTemp; m_pBar->GetWindowRect(rectTemp); if (rectTemp.Size() != m_rectDragFrame.Size()) { if (CRect().IntersectRect(XTPMultiMonitor()->GetWorkArea(m_pBar), m_rectDragFrame)) { ((CXTPDialogBar*)m_pBar)->OnResize(m_rectDragFrame, m_nHitTest); m_pBar->Redraw(); } } m_ptLast = pt; } void CXTPDockContext::Stretch(CPoint pt) { CPoint ptOffset = pt - m_ptLast; DWORD dwMode = LM_HORZ | LM_COMMIT; int nLength = 0; if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT) { if (m_nHitTest == HTLEFT) m_rectDragFrame.left += ptOffset.x; else m_rectDragFrame.right += ptOffset.x; nLength = m_rectDragFrame.Width(); } else { dwMode |= LM_LENGTHY; if (m_nHitTest == HTTOP) m_rectDragFrame.top += ptOffset.y; else m_rectDragFrame.bottom += ptOffset.y; nLength = m_rectDragFrame.Height(); } nLength = (nLength >= 0) ? nLength : 0; CSize size = m_pBar->CalcDynamicLayout(nLength, dwMode); CRect rectTemp; m_pBar->GetWindowRect(rectTemp); if (rectTemp.Size() != size) { if (m_nHitTest == HTRIGHT || m_nHitTest == HTBOTTOM) { rectTemp.BottomRight() = rectTemp.TopLeft() + size; } else if (m_nHitTest == HTLEFT) { rectTemp.bottom = rectTemp.top + size.cy; rectTemp.left = rectTemp.right - size.cx; } else if (m_nHitTest == HTTOP) { rectTemp.top = rectTemp.bottom - size.cy; rectTemp.right = rectTemp.left + size.cx; } CRect rcWork = XTPMultiMonitor()->GetWorkArea(m_pBar); if (!CRect().IntersectRect(rcWork, rectTemp)) { if (rectTemp.right < rcWork.left) rectTemp.OffsetRect(rcWork.left - rectTemp.left, 0); else if (rectTemp.left > rcWork.right) rectTemp.OffsetRect(rcWork.right - rectTemp.right, 0); if (rectTemp.bottom < rcWork.top) rectTemp.OffsetRect(0, rcWork.top - rectTemp.top); else if (rectTemp.top > rcWork.bottom) rectTemp.OffsetRect(0, rcWork.bottom - rectTemp.bottom); } m_pBar->MoveWindow(rectTemp); m_pBar->Redraw(); } m_ptLast = pt; } BOOL CXTPDockContext::ToggleDocking() { CXTPCommandBars* pCommandBars = m_pBar->GetCommandBars(); if (m_pBar->GetPosition() == xtpBarFloating) { // Dock it only if is allowed to be docked if (!(m_pBar->m_dwFlags & xtpFlagAlignAny)) return FALSE; CRect rect = m_rectMRUDockPos; CXTPDockBar* pDockBar = pCommandBars->GetDockBar(m_uMRUDockPosition); pDockBar->ClientToScreen(&rect); // dock it at the specified position, RecalcLayout will snap pCommandBars->DockCommandBar(m_pBar, &rect, pDockBar); pCommandBars->RecalcFrameLayout(); } else { if (!(m_pBar->m_dwFlags & xtpFlagFloating)) return FALSE; if (!pCommandBars->GetCommandBarsOptions()->bDblClickFloat) return FALSE; CPoint ptFloat = m_ptMRUFloatPos; if (ptFloat.x <= 0 || ptFloat.y <= 0) { ptFloat = m_rectMRUDockPos.TopLeft(); m_pBar->GetParent()->ClientToScreen(&ptFloat); } pCommandBars->FloatCommandBar(m_pBar); CSize sz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT); m_pBar->MoveWindow(CRect(ptFloat, sz)); } pCommandBars->GetCommandBarsOptions()->bDirtyState = TRUE; return TRUE; }