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

📄 controlbarex.cpp

📁 MFC类库祥解, MFC类库祥解
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
		::GetSysColor(COLOR_BTNSHADOW));

	m_biHide.Paint(pDC);

}

void CControlBarEx::OnPaint()
{
	// overridden to skip border painting based on clientrect
	CPaintDC dc(this);
}

UINT CControlBarEx::OnNcHitTest(CPoint point)
{

	CRect rcBar, rcEdge;
	GetWindowRect(rcBar);

	if (!IsFloating())
		for (int i = 0; i < 4; i++)
			if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
				if (rcEdge.PtInRect(point))
					return GetEdgeHTCode(i);

	CRect rc = m_biHide.GetRect();
	rc.OffsetRect(rcBar.TopLeft());
	if (rc.PtInRect(point))
		return HTCLOSE;

	return HTCLIENT;
}

void CControlBarEx::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
	CControlBar::OnSettingChange(uFlags, lpszSection);

	m_bDragShowContent = FALSE;
	::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
		&m_bDragShowContent, 0); // update
}

void CControlBarEx::OnSize(UINT nType, int cx, int cy)
{
	CWnd *pWnd = GetWindow(GW_CHILD);

	if ( pWnd != NULL )
		pWnd->MoveWindow(0,0,cx,cy);
}

void CControlBarEx::OnClose()
{
	// do nothing: protection against accidentally destruction by the
	//	 child control (i.e. if user hits Esc in a child editctrl)
}

/////////////////////////////////////////////////////////////////////////
// CControlBarEx implementation helpers

void CControlBarEx::StartTracking(UINT nHitTest, CPoint point)
{
	SetCapture();

	// make sure no updates are pending
	if (!m_bDragShowContent)
		RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);

	m_htEdge = nHitTest;
	m_bTracking = TRUE;

	BOOL bHorz = IsHorzDocked();
	BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;

	m_nTrackPosOld = bHorzTracking ? point.x : point.y;

	CRect rcBar, rcEdge;
	GetWindowRect(rcBar);
	GetEdgeRect(rcBar, m_htEdge, rcEdge);
	m_nTrackEdgeOfs = m_nTrackPosOld -
		(bHorzTracking ? rcEdge.CenterPoint().x : rcEdge.CenterPoint().y);
	
	CSCBArray arrSCBars;
	int nThis;
	GetRowSizingBars(arrSCBars, nThis);

	m_nTrackPosMin = m_nTrackPosMax = m_nTrackPosOld;
	if (!IsSideTracking())
	{
		// calc minwidth as the max minwidth of the sizing bars on row
		int nMinWidth = bHorz ? m_szMinHorz.cy : m_szMinVert.cx;
		for (int i = 0; i < arrSCBars.GetSize(); i++)
			nMinWidth = max(nMinWidth, bHorz ? 
				arrSCBars[i]->m_szMinHorz.cy :
				arrSCBars[i]->m_szMinVert.cx);
		int nExcessWidth = (bHorz ? m_szHorz.cy : m_szVert.cx) - nMinWidth;

		// the control bar cannot grow with more than the width of
		// remaining client area of the mainframe
		CRect rcT;
		m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
			reposQuery, &rcT, NULL, TRUE);
		int nMaxWidth = bHorz ? rcT.Height() - 2 : rcT.Width() - 2;

		BOOL bTopOrLeft = m_htEdge == HTTOP || m_htEdge == HTLEFT;

		m_nTrackPosMin -= bTopOrLeft ? nMaxWidth : nExcessWidth;
		m_nTrackPosMax += bTopOrLeft ? nExcessWidth : nMaxWidth;
	}
	else
	{
		// side tracking:
		// max size is the actual size plus the amount the other
		// sizing bars can be decreased until they reach their minsize
		if (m_htEdge == HTBOTTOM || m_htEdge == HTRIGHT)
			nThis++;

		for (int i = 0; i < arrSCBars.GetSize(); i++)
		{
			CControlBarEx* pBar = arrSCBars[i];

			int nExcessWidth = bHorz ? 
				pBar->m_szHorz.cx - pBar->m_szMinHorz.cx :
				pBar->m_szVert.cy - pBar->m_szMinVert.cy;

			if (i < nThis)
				m_nTrackPosMin -= nExcessWidth;
			else
				m_nTrackPosMax += nExcessWidth;
		}
	}

	OnTrackInvertTracker(); // draw tracker
}

void CControlBarEx::StopTracking()
{
	OnTrackInvertTracker(); // erase tracker

	m_bTracking = FALSE;
	ReleaseCapture();

	m_pDockSite->DelayRecalcLayout();
}

void CControlBarEx::OnTrackUpdateSize(CPoint& point)
{
	ASSERT(!IsFloating());

	BOOL bHorzTrack = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;

	int nTrackPos = bHorzTrack ? point.x : point.y;
	nTrackPos = max(m_nTrackPosMin, min(m_nTrackPosMax, nTrackPos));

	int nDelta = nTrackPos - m_nTrackPosOld;

	if (nDelta == 0)
		return; // no pos change

	OnTrackInvertTracker(); // erase tracker

	m_nTrackPosOld = nTrackPos;
	
	BOOL bHorz = IsHorzDocked();

	CSize sizeNew = bHorz ? m_szHorz : m_szVert;
	switch (m_htEdge)
	{
	case HTLEFT:	sizeNew -= CSize(nDelta, 0); break;
	case HTTOP: 	sizeNew -= CSize(0, nDelta); break;
	case HTRIGHT:	sizeNew += CSize(nDelta, 0); break;
	case HTBOTTOM:	sizeNew += CSize(0, nDelta); break;
	}

	CSCBArray arrSCBars;
	int nThis;
	GetRowSizingBars(arrSCBars, nThis);

	if (!IsSideTracking())
		for (int i = 0; i < arrSCBars.GetSize(); i++)
		{
			CControlBarEx* pBar = arrSCBars[i];
			// make same width (or height)
			(bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
				bHorz ? sizeNew.cy : sizeNew.cx;
		}
	else
	{
		int nGrowingBar = nThis;
		BOOL bBefore = m_htEdge == HTTOP || m_htEdge == HTLEFT;
		if (bBefore && nDelta > 0)
			nGrowingBar--;
		if (!bBefore && nDelta < 0)
			nGrowingBar++;
		if (nGrowingBar != nThis)
			bBefore = !bBefore;

		// nGrowing is growing
		nDelta = abs(nDelta);
		CControlBarEx* pBar = arrSCBars[nGrowingBar];
		(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta;

		// the others are shrinking
		int nFirst = bBefore ? nGrowingBar - 1 : nGrowingBar + 1;
		int nLimit = bBefore ? -1 : arrSCBars.GetSize();

		for (int i = nFirst; nDelta != 0 && i != nLimit; i += (bBefore ? -1 : 1))
		{
			CControlBarEx* pBar = arrSCBars[i];
				
			int nDeltaT = min(nDelta,
				(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -
				(bHorz ? pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy));

			(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= nDeltaT;
			nDelta -= nDeltaT;
		}
	}

	OnTrackInvertTracker(); // redraw tracker at new pos

	if (m_bDragShowContent)
		m_pDockSite->DelayRecalcLayout();
}

void CControlBarEx::OnTrackInvertTracker()
{
	ASSERT(m_bTracking);

	if (m_bDragShowContent)
		return; // don't show tracker if DragFullWindows is on

	BOOL bHorz = IsHorzDocked();
	CRect rc, rcBar, rcDock, rcFrame;
	GetWindowRect(rcBar);
	m_pDockBar->GetWindowRect(rcDock);
	m_pDockSite->GetWindowRect(rcFrame);
	VERIFY(GetEdgeRect(rcBar, m_htEdge, rc));
	if (!IsSideTracking())
		rc = bHorz ? 
			CRect(rcDock.left + 1, rc.top, rcDock.right - 1, rc.bottom) :
			CRect(rc.left, rcDock.top + 1, rc.right, rcDock.bottom - 1);

	BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
	int nOfs = m_nTrackPosOld - m_nTrackEdgeOfs;
	nOfs -= bHorzTracking ? rc.CenterPoint().x : rc.CenterPoint().y;
	rc.OffsetRect(bHorzTracking ? nOfs : 0, bHorzTracking ? 0 : nOfs);
	rc.OffsetRect(-rcFrame.TopLeft());

	CDC *pDC = m_pDockSite->GetDCEx(NULL,
		DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
	CBrush* pBrush = CDC::GetHalftoneBrush();
	CBrush* pBrushOld = pDC->SelectObject(pBrush);

	pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
	
	pDC->SelectObject(pBrushOld);
	m_pDockSite->ReleaseDC(pDC);
}

BOOL CControlBarEx::GetEdgeRect(CRect rcWnd, UINT nHitTest,
									CRect& rcEdge)
{
	rcEdge = rcWnd;
	rcEdge.DeflateRect(1, 1);
	BOOL bHorz = IsHorzDocked();

	switch (nHitTest)
	{
	case HTLEFT:
		if (!(m_dwSCBStyle & CBRS_BORDER_LEFT)) return FALSE;
		rcEdge.right = rcEdge.left + m_cxEdge+1;
		if ( bHorz )
			rcEdge.bottom -= m_cxEdge;
		break;
	case HTTOP:
		if (!(m_dwSCBStyle & CBRS_BORDER_TOP)) return FALSE;
		rcEdge.bottom = rcEdge.top + m_cxEdge+1;
		if ( !bHorz )
			rcEdge.right -= m_cxEdge;
		break;
	case HTRIGHT:
		if (!(m_dwSCBStyle & CBRS_BORDER_RIGHT)) return FALSE;
		rcEdge.left = rcEdge.right - m_cxEdge;

		if ( bHorz )
			rcEdge.bottom -= m_cxEdge;
		break;
	case HTBOTTOM:
		if (!(m_dwSCBStyle & CBRS_BORDER_BOTTOM)) return FALSE;
		rcEdge.top = rcEdge.bottom - m_cxEdge-1;
		if ( !bHorz )
			rcEdge.right -= m_cxEdge;
		break;
	default:
		ASSERT(FALSE); // invalid hit test code
	}
	return TRUE;
}

UINT CControlBarEx::GetEdgeHTCode(int nEdge)
{
	if (nEdge == 0) return HTLEFT;
	if (nEdge == 1) return HTTOP;
	if (nEdge == 2) return HTRIGHT;
	if (nEdge == 3) return HTBOTTOM;
	ASSERT(FALSE); // invalid edge code
	return HTNOWHERE;
}

void CControlBarEx::GetRowInfo(int& nFirst, int& nLast, int& nThis)
{
	ASSERT_VALID(m_pDockBar); // verify bounds

	nThis = m_pDockBar->FindBar(this);
	ASSERT(nThis != -1);

	int i, nBars = m_pDockBar->m_arrBars.GetSize();

	// find the first and the last bar in row
	for (nFirst = -1, i = nThis - 1; i >= 0 && nFirst == -1; i--)
		if (m_pDockBar->m_arrBars[i] == NULL)
			nFirst = i + 1;
	for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
		if (m_pDockBar->m_arrBars[i] == NULL)
			nLast = i - 1;

	ASSERT((nLast != -1) && (nFirst != -1));
}

void CControlBarEx::GetRowSizingBars(CSCBArray& arrSCBars)
{
	int nThis; // dummy
	GetRowSizingBars(arrSCBars, nThis);
}

void CControlBarEx::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
{
	arrSCBars.RemoveAll();

	int nFirstT, nLastT, nThisT;
	GetRowInfo(nFirstT, nLastT, nThisT);

	nThis = -1;
	for (int i = nFirstT; i <= nLastT; i++)
	{
		CControlBarEx* pBar =
			(CControlBarEx*) m_pDockBar->m_arrBars[i];
		if (HIWORD(pBar) == 0) continue; // placeholder
		if (!pBar->IsVisible()) continue;
		if (pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx)))
		{
			if (pBar == this)
				nThis = arrSCBars.GetSize();

			arrSCBars.Add(pBar);
		}
	}
}

BOOL CControlBarEx::NegotiateSpace(int nLengthTotal, BOOL bHorz)
{
	int nFirst, nLast, nThis;
	GetRowInfo(nFirst, nLast, nThis);

	int nLengthAvail = nLengthTotal;
	int nLengthActual = 0;
	int nLengthMin = 2;
	int nWidthMax = 0;
	CControlBarEx* pBar;

	for (int i = nFirst; i <= nLast; i++)
	{
		pBar = (CControlBarEx*) m_pDockBar->m_arrBars[i];
		if (HIWORD(pBar) == 0) continue; // placeholder
		if (!pBar->IsVisible()) continue;
		BOOL bIsSizingBar = pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx));

		int nLengthBar; // minimum length of the bar
		if (bIsSizingBar)
			nLengthBar = bHorz ? pBar->m_szMinHorz.cx - 2 :	pBar->m_szMinVert.cy - 2;
		else
		{
			CRect rcBar;
			pBar->GetWindowRect(&rcBar);
			nLengthBar = bHorz ? rcBar.Width() - 2 : rcBar.Height() - 2;
		}

		nLengthMin += nLengthBar;
		if (nLengthMin > nLengthTotal)
		{
			// split the row after fixed bar
			if (i < nThis)
			{
				m_pDockBar->m_arrBars.InsertAt(i + 1,(CControlBar*) NULL);
				return FALSE;
			}
			
			// only this sizebar remains on the row, adjust it to minsize
			if (i == nThis)
			{
				if (bHorz)
					m_szHorz.cx = m_szMinHorz.cx;
				else
					m_szVert.cy = m_szMinVert.cy;

				return TRUE; // the dockbar will split the row for us
			}

			// we have enough bars - go negotiate with them
			m_pDockBar->m_arrBars.InsertAt(i, (CControlBar*) NULL);
			nLast = i - 1;
			break;
		}

		if (bIsSizingBar)
		{
			nLengthActual += bHorz ? pBar->m_szHorz.cx - 2 : pBar->m_szVert.cy - 2;
			nWidthMax = max(nWidthMax, bHorz ? pBar->m_szHorz.cy :pBar->m_szVert.cx);
		}
		else
			nLengthAvail -= nLengthBar;
	}

	CSCBArray arrSCBars;
	GetRowSizingBars(arrSCBars);
	int nNumBars = arrSCBars.GetSize();
	int nDelta = nLengthAvail - nLengthActual;

	// return faster when there is only one sizing bar per row (this one)
	if (nNumBars == 1)
	{
		ASSERT(arrSCBars[0] == this);

		if (nDelta == 0)
			return TRUE;
		
		m_bKeepSize = FALSE;
		(bHorz ? m_szHorz.cx : m_szVert.cy) += nDelta;

		return TRUE;
	}

	// make all the bars the same width
	for (i = 0; i < nNumBars; i++)
		if (bHorz)
			arrSCBars[i]->m_szHorz.cy = nWidthMax;
		else
			arrSCBars[i]->m_szVert.cx = nWidthMax;

	// distribute the difference between the bars,
	// but don't shrink them below their minsizes
	while (nDelta != 0)
	{
		int nDeltaOld = nDelta;
		for (i = 0; i < nNumBars; i++)
		{
			pBar = arrSCBars[i];
			int nLMin = bHorz ?
				pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy;
			int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;

			if ((nL == nLMin) && (nDelta < 0) || // already at min length
				pBar->m_bKeepSize) // or wants to keep its size
				continue;

			// sign of nDelta
			int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);

			(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta2;
			nDelta -= nDelta2;
			if (nDelta == 0) break;
		}
		// clear m_bKeepSize flags
		if ((nDeltaOld == nDelta) || (nDelta == 0))
			for (i = 0; i < nNumBars; i++)
				arrSCBars[i]->m_bKeepSize = FALSE;
	}

	return TRUE;
}

void CControlBarEx::AlignControlBars()
{
	int nFirst, nLast, nThis;
	GetRowInfo(nFirst, nLast, nThis);

	BOOL bHorz = IsHorzDocked();
	BOOL bNeedRecalc = FALSE;
	int nAlign = bHorz ? -2 : 0;

	CRect rc, rcDock;
	m_pDockBar->GetWindowRect(&rcDock);

	for (int i = nFirst; i <= nLast; i++)
	{
		CControlBarEx* pBar =
			(CControlBarEx*) m_pDockBar->m_arrBars[i];
		if (HIWORD(pBar) == 0) continue; // placeholder
		if (!pBar->IsVisible()) continue;

		pBar->GetWindowRect(&rc);
		rc.OffsetRect(-rcDock.TopLeft());

		if (pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx)))
			rc = CRect(rc.TopLeft(),
				bHorz ? pBar->m_szHorz : pBar->m_szVert);

		if ((bHorz ? rc.left : rc.top) != nAlign)
		{
			if (!bHorz)
				rc.OffsetRect(0, nAlign - rc.top - 2);
			else if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
				rc.OffsetRect(nAlign - rc.left, -2);
			else
				rc.OffsetRect(nAlign - rc.left, 0);
			pBar->MoveWindow(rc);
			bNeedRecalc = TRUE;
		}
		nAlign += (bHorz ? rc.Width() : rc.Height()) - 2;
	}

	if (bNeedRecalc)
		m_pDockSite->DelayRecalcLayout();
}

void CControlBarEx::OnUpdateCmdUI(CFrameWnd* pTarget,BOOL bDisableIfNoHndler)
{
	if ( IsFloating() )
		return;

	BOOL bNeedPaint = FALSE;

	CPoint pt;
	::GetCursorPos(&pt);
	BOOL bHit = (OnNcHitTest(pt) == HTCLOSE);
	BOOL bLButtonDown = (::GetKeyState(VK_LBUTTON) < 0);

	BOOL bWasPushed = m_biHide.bPushed;
	m_biHide.bPushed = bHit && bLButtonDown;

	BOOL bWasRaised = m_biHide.bRaised;
	m_biHide.bRaised = bHit && !bLButtonDown;

	bNeedPaint |= (m_biHide.bPushed ^ bWasPushed) ||
				  (m_biHide.bRaised ^ bWasRaised);

	if (bNeedPaint)
		SendMessage(WM_NCPAINT);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -