📄 guidockcontext.cpp
字号:
//-----------------------------------------------------------------------//
// This is a part of the GuiLib MFC Extention. //
// Autor : Francisco Campos //
// (C) 2002 Francisco Campos <www.beyondata.com> 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 //
// fco_campos@tutopia.com //
//-----------------------------------------------------------------------//
#include "stdafx.h"
#include "..\header\GuiDockContext.h"
#include "..\header\GuiToolBarWnd.h"
#include "..\header\MenuBar.h"
#include "..\header\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 _AfxGuiAdjustRectangle(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;
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);
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);
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
_AfxGuiAdjustRectangle(m_rectDragHorz, pt);
_AfxGuiAdjustRectangle(m_rectDragVert, pt);
_AfxGuiAdjustRectangle(m_rectFrameDragHorz, pt);
_AfxGuiAdjustRectangle(m_rectFrameDragVert, pt);
// initialize tracking state and enter tracking loop
m_dwOverDockStyle = CanDock();
Move(pt); // call it here to handle special keys
m_pDockSite->RecalcLayout();
Track();
m_pDockSite->RecalcLayout();
}
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);
}
bFirstClic=TRUE;
bSecondClic=TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -