📄 dockpagebar.cpp
字号:
pItem->m_TabWidth = dc.GetTextExtent (sText).cx;
if(IconID)
{
pItem->m_hIcon = AfxGetApp()->LoadIcon(IconID);
pItem->m_TabWidth += 18;
}
else
pItem->m_hIcon = NULL;
pItem->m_TabWidth += 9;
if(pWnd)
{
CRect rect;
GetClientRect(rect, m_PageList.GetCount()>1?TRUE:FALSE);
pWnd->MoveWindow(rect);
pWnd->ShowWindow(SW_HIDE);
}
m_PageList.AddTail(pItem);
UpdateWindow();
return TRUE;
}
BOOL CDockPageBar::AddPage(CPageItem *pPageItem)
{
CPageItem *pItem;
pItem = new CPageItem();
memcpy(pItem, pPageItem, sizeof(CPageItem));
pItem->m_pWnd->SetParent (this);
m_PageList.AddTail(pItem);
//m_nActivePage = -1;
UpdateWindow();
return TRUE;
}
BOOL CDockPageBar::AddPage(CDockPageBar *dockPageBar)
{
POSITION pos;
CPageItem* pItem;
for(pos = dockPageBar->m_PageList.GetHeadPosition();pos!=NULL;)
{
pItem=(CPageItem*)dockPageBar->m_PageList.GetNext(pos);
if(pItem)
{
AddPage(pItem);
}
}
dockPageBar->m_pDockContext->m_pDockSite->FloatControlBar(dockPageBar,CSize(0,0),0);
dockPageBar->m_PageList.RemoveAll();
UpdateWindow();
return dockPageBar->DestroyWindow ();
}
CPageItem* CDockPageBar::DeletePage()
{
CPageItem *pItem = NULL;
POSITION pos = m_PageList.FindIndex(m_nActivePage);
if(!pos)
{
return NULL;
}
pItem = (CPageItem*)m_PageList.GetAt(pos);
pItem->m_pWnd->ShowWindow(SW_HIDE);
m_PageList.RemoveAt (pos);
m_nActivePage = -1;
UpdateWindow();
return pItem;
}
void CDockPageBar::UpdateWindow()
{
UpdateSize();
if(m_nActivePage < 0)
SetActivePage(0);
Invalidate(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
//
void CDockPageBar::OnPaint()
{
CPaintDC dc(this);
if(m_PageList.GetCount() == 0)
return;
CPageItem *pItem;
POSITION pos;
int nItemIndex = 0;
CRect rect;
GetClientRect(rect, FALSE);
rect.left +=1;
rect.right -=1;
rect.bottom -=1;
rect.top = rect.bottom - ITEMBUTTON_HEIGHT + 4;
CBrush brush(RGB(247,243,233));
dc.FillRect(rect,&brush);
CPen pen(PS_SOLID,1,GetSysColor(COLOR_3DDKSHADOW));
HPEN oldPen = (HPEN)dc.SelectObject (&pen);
dc.MoveTo (rect.TopLeft() );
dc.LineTo (rect.right, rect.top);
dc.SelectObject (oldPen);
HFONT oldFont = (HFONT)dc.SelectObject (m_font);
// draw PageItem
for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++)
{
pItem=(CPageItem*)m_PageList.GetNext(pos);
if(pItem)
{
pItem->Draw(&dc,(m_nActivePage==nItemIndex)?TRUE:FALSE);
}
}
dc.SelectObject (oldFont);
}
void CDockPageBar::OnLButtonDown(UINT nFlags, CPoint point)
{
UINT nItemIndex=0;
POSITION pos;
CPageItem *pItem;
SetFocus();
for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++)
{
pItem=(CPageItem*)m_PageList.GetNext(pos);
if(pItem)
{
if(pItem->m_rect.PtInRect(point))
{
SetActivePage(nItemIndex);
CanDrag(point); // drag PageItem
return;
}
}
}
((CDockPageBarContext*)m_pDockContext)->m_isPage = FALSE;
//baseCDockPageBar::OnLButtonDown(nFlags, point);
if (m_pDockBar != NULL)
{
// start the drag
ASSERT(m_pDockContext != NULL);
ClientToScreen(&point);
m_pDockContext->StartDrag(point);
}
else
CWnd::OnLButtonDown(nFlags, point);
}
void CDockPageBar::EnableDocking(DWORD dwDockStyle)
{
// must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
// cannot have the CBRS_FLOAT_MULTI style
ASSERT((dwDockStyle & CBRS_FLOAT_MULTI) == 0);
// the bar must have CBRS_SIZE_DYNAMIC style
ASSERT((m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
m_dwDockStyle = dwDockStyle;
if (m_pDockContext == NULL)
m_pDockContext = new CDockPageBarContext(this);
// permanently wire the bar's owner to its current parent
if (m_hWndOwner == NULL)
m_hWndOwner = ::GetParent(m_hWnd);
}
void CDockPageBar::CanDrag(CPoint pt)
{
SetCapture();
// get messages until capture lost or cancelled/accepted
while (CWnd::GetCapture() == this)
{
MSG msg;
if (!::GetMessage(&msg, NULL, 0, 0))
{
AfxPostQuitMessage(msg.wParam);
break;
}
switch (msg.message)
{
case WM_LBUTTONUP:
ReleaseCapture();
break;
case WM_MOUSEMOVE:
Move(msg.pt);
break;
default:
DispatchMessage(&msg);
break;
}
}
}
void CDockPageBar::Move(CPoint pt)
{
CRect rect;
GetClientRect(&rect, FALSE);
rect.top = rect.bottom - ITEMBUTTON_HEIGHT - 5;
ScreenToClient(&pt);
if(rect.PtInRect(pt))
{
int nItemIndex=0;
POSITION pos;
CPageItem *pItem;
for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++)
{
pItem=(CPageItem*)m_PageList.GetNext(pos);
if(pItem)
{
if(pItem->m_rect.PtInRect(pt))
{
if(nItemIndex != m_nActivePage)
{
POSITION oldPos = m_PageList.FindIndex(m_nActivePage);
POSITION curPos = m_PageList.FindIndex(nItemIndex);
CPageItem *pOldItem = (CPageItem*)m_PageList.GetAt(oldPos);
// exchange PageItem
m_PageList.SetAt(oldPos, pItem);
m_PageList.SetAt(curPos, pOldItem);
m_nActivePage = nItemIndex;
UpdateWindow();
break;
}
}
}
}
}
else
{
ReleaseCapture();
StartDrag(pt);
}
}
void CDockPageBar::StartDrag(CPoint pt)
{
ClientToScreen(&pt);
((CDockPageBarContext*)m_pDockContext)->m_isPage = TRUE;
m_pDockContext->StartDrag(pt);
((CDockPageBarContext*)m_pDockContext)->m_isPage = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CDockPageBarContext
#define _AfxGetDlgCtrlID(hWnd) ((UINT)(WORD)::GetDlgCtrlID(hWnd))
#define CX_BORDER 1
#define CY_BORDER 1
#define CBRS_ALIGN_INSERT_PAGE 0x0001L // drag to another CDockPageBar
#define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
#define VERTF(dw) (dw & CBRS_ORIENT_VERT)
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);
}
void CDockPageBarContext::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
_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();
}
BOOL CDockPageBarContext::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;
}
void CDockPageBarContext::Move(CPoint pt)
{
CPoint ptOffset = pt - m_ptLast;
if(TRUE == isDockPage(pt))
{
m_dwOverDockStyle = CBRS_ALIGN_INSERT_PAGE;
}
else
{
// offset all drag rects to new position
m_rectDragHorz.OffsetRect(ptOffset);
m_rectFrameDragHorz.OffsetRect(ptOffset);
m_rectDragVert.OffsetRect(ptOffset);
m_rectFrameDragVert.OffsetRect(ptOffset);
// if control key is down don't dock
m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
}
m_ptLast = pt;
// update feedback
if(FALSE == m_isMe)
DrawFocusRect();
else
DrawFocusRect(TRUE);
}
// get the target CDockPageBar on mouse move
BOOL CDockPageBarContext::isDockPage(CPoint pt)
{
m_isMe = FALSE;
HWND hWnd = WindowFromPoint(pt);
CDockPageBar* pBar = (CDockPageBar*)CWnd::FromHandle (hWnd);
if(pBar->IsKindOf (RUNTIME_CLASS(CDockPageBar)))
{
if(pBar != m_pBar)
{
CRect rect;
pBar->GetWindowRect (&rect);
rect.bottom = rect.top + pBar->m_cyGripper;
if(rect.PtInRect (pt))
{
m_pTgDockPage = pBar;
pBar->GetWindowRect (&m_addRect);
return TRUE;
}
}
else
{
m_isMe = TRUE;
}
}
m_pTgDockPage = NULL;
return FALSE;
}
void CDockPageBarContext::EndDrag()
{
CancelLoop();
// drag to another CDockPageBar
if((NULL != m_pTgDockPage) && (m_dwOverDockStyle == CBRS_ALIGN_INSERT_PAGE))
{
if(TRUE == m_isPage) // drag PageItem
{
CPageItem * pItem = (CPageItem *)((CDockPageBar*)m_pBar)->DeletePage ();
m_pTgDockPage->AddPage(pItem);
}
else // drag a CDockPageBar object to another CDockPageBar
{
m_pTgDockPage->AddPage((CDockPageBar*)m_pBar);
}
return;
}
CControlBar* pBar;
if(TRUE == m_isPage) // drag PageItem (dock or float)
pBar = CreateNewBar();
else
pBar = m_pBar; // drag CDockPageBar
if(NULL == pBar)
return;
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(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(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(pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
}
}
CDockPageBar* CDockPageBarContext::CreateNewBar()
{
CPageItem * pItem = (CPageItem *)((CDockPageBar*)m_pBar)->DeletePage ();
CDockPageBar* pBar = new CDockPageBar();
if (!(pBar->Create(_T("New Bar"), m_pDockSite, 12345)))
{
TRACE0("Failed to create mybar\n");
return NULL; // fail to create
}
pBar->SetBarStyle(m_pBar->GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
pBar->EnableDocking(CBRS_ALIGN_ANY);
pBar->AddPage (pItem);
return pBar;
}
void CDockPageBarContext::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(m_dwOverDockStyle == CBRS_ALIGN_INSERT_PAGE)
rect = m_addRect; // rect of target CDockPageBar
// draw it and remember last size
m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
m_rectLast = rect;
m_sizeLast = size;
m_bDitherLast = (pBrush == pDitherBrush);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -