⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dockpagebar.cpp

📁 路由信息查看程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -