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

📄 controlbarex.cpp

📁 MFC类库祥解, MFC类库祥解
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "ControlBarEx.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif



/////////////////////////////////////////////////////////////////////////
// CSCBButton

CControlBarEx::CSCBButton::CSCBButton()
{
	bRaised = FALSE;
	bPushed = FALSE;
}

void CControlBarEx::CSCBButton::Paint(CDC* pDC)
{
	CRect rc = GetRect();

	if (bPushed)
		pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNSHADOW),::GetSysColor(COLOR_BTNHIGHLIGHT));
	else
		if (bRaised)
			pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNHIGHLIGHT),::GetSysColor(COLOR_BTNSHADOW));

	COLORREF clrOldTextColor = pDC->GetTextColor();
	pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
	int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
	CFont font;
	int ppi = pDC->GetDeviceCaps(LOGPIXELSX);
	int pointsize = MulDiv(60, 96, ppi); // 6 points at 96 ppi
	font.CreatePointFont(pointsize, _T("Marlett"));
	CFont* oldfont = pDC->SelectObject(&font);

	pDC->TextOut(ptOrg.x + 2, ptOrg.y + 2, CString(_T("r"))); // x-like

	pDC->SelectObject(oldfont);
	pDC->SetBkMode(nPrevBkMode);
	pDC->SetTextColor(clrOldTextColor);
}

/////////////////////////////////////////////////////////////////////////
// CControlBarEx

#define CBRS_BORDER_ALL		(CBRS_BORDER_LEFT|CBRS_BORDER_RIGHT|CBRS_BORDER_TOP|CBRS_BORDER_BOTTOM)

IMPLEMENT_DYNAMIC(CControlBarEx, CControlBar);

CControlBarEx::CControlBarEx()
{
	m_szMinHorz = CSize(33, 32);
	m_szMinVert = CSize(33, 32);
	m_szMinFloat = CSize(37, 32);
	m_szHorz = CSize(200, 200);
	m_szVert = CSize(200, 200);
	m_szFloat = CSize(200, 200);
	m_bTracking = FALSE;
	m_bKeepSize = FALSE;
	m_bParentSizing = FALSE;
	m_cxEdge = 5;
	m_bDragShowContent = FALSE;
	m_nDockBarID = 0;
	m_dwSCBStyle = 0;

	m_cyGripper = 12;

}

CControlBarEx::~CControlBarEx()
{
}

BEGIN_MESSAGE_MAP(CControlBarEx, CControlBar)
	//{{AFX_MSG_MAP(CControlBarEx)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_NCPAINT()
	ON_WM_NCCALCSIZE()
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_CAPTURECHANGED()
	ON_WM_SETTINGCHANGE()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_NCLBUTTONDOWN()
	ON_WM_NCLBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_NCMOUSEMOVE()
	ON_WM_NCHITTEST()
	ON_WM_CLOSE()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_SETTEXT, OnSetText)
END_MESSAGE_MAP()

// preffered creation method
BOOL CControlBarEx::Create(LPCTSTR lpszWindowName,CWnd* pParentWnd, UINT nID,DWORD dwStyle)
{
	// must have a parent
	ASSERT_VALID(pParentWnd);
	// cannot be both fixed and dynamic
	// (CBRS_SIZE_DYNAMIC is used for resizng when floating)
	//ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
	dwStyle &= ~CBRS_SIZE_FIXED;
	dwStyle |= CBRS_SIZE_DYNAMIC;

	m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles

	// register and create the window - skip CControlBar::Create()
	CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW),::GetSysColorBrush(COLOR_BTNFACE), 0);

	dwStyle &= ~CBRS_ALL; // keep only the generic window styles
	dwStyle |= WS_CLIPCHILDREN; // prevents flashing
	return CWnd::Create(wndclass, lpszWindowName, dwStyle, CRect(0, 0, 0, 0), pParentWnd, nID);
}

/////////////////////////////////////////////////////////////////////////
// CControlBarEx message handlers

int CControlBarEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CControlBar::OnCreate(lpCreateStruct) == -1)
		return -1;

	// query SPI_GETDRAGFULLWINDOWS system parameter
	// OnSettingChange() will update m_bDragShowContent
	m_bDragShowContent = FALSE;
	::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bDragShowContent, 0);

	return 0;
}


LRESULT CControlBarEx::OnSetText(WPARAM wParam, LPARAM lParam)
{
	UNUSED_ALWAYS(wParam);

	LRESULT lResult = CWnd::Default();

	if (IsFloating() && GetParentFrame()->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
	{
		m_pDockBar->SetWindowText((LPCTSTR) lParam); // update dockbar
		GetParentFrame()->DelayRecalcLayout(); // refresh miniframe
	}

	return lResult;
}

const BOOL CControlBarEx::IsFloating() const
{
	return !IsHorzDocked() && !IsVertDocked();
}

const BOOL CControlBarEx::IsHorzDocked() const
{
	return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP || m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
}

const BOOL CControlBarEx::IsVertDocked() const
{
	return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT || m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
}

const BOOL CControlBarEx::IsSideTracking() const
{
	// don't call this when not tracking
	ASSERT(m_bTracking && !IsFloating());

	return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ? IsHorzDocked() : IsVertDocked();
}

CSize CControlBarEx::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
	if (bStretch) // the bar is stretched (is not the child of a dockbar)
		return bHorz? CSize(32767, m_szHorz.cy): CSize(m_szVert.cx, 32767);

	// dirty cast - we need access to protected CDockBar members
	CSCBDockBar* pDockBar = (CSCBDockBar*) m_pDockBar;

	// force imediate RecalcDelayShow() for all sizing bars on the row
	// with delayShow/delayHide flags set to avoid IsVisible() problems
	CSCBArray arrSCBars;
	GetRowSizingBars(arrSCBars);
	AFX_SIZEPARENTPARAMS layout;
	layout.hDWP = pDockBar->m_bLayoutQuery ?NULL: ::BeginDeferWindowPos(arrSCBars.GetSize());
	for (int i = 0; i < arrSCBars.GetSize(); i++)
	{
		if (arrSCBars[i]->m_nStateFlags & (delayHide|delayShow))
			arrSCBars[i]->RecalcDelayShow(&layout);
	}
	if (layout.hDWP != NULL)
		::EndDeferWindowPos(layout.hDWP);

	// get available length
	CRect rc = pDockBar->m_rectLayout;
	if (rc.IsRectEmpty())
		m_pDockSite->GetClientRect(&rc);
	int nLengthTotal = bHorz ? rc.Width() + 2 : rc.Height() - 2;

	if (IsVisible() && !IsFloating() && m_bParentSizing && arrSCBars[0] == this)
		if (NegotiateSpace(nLengthTotal, (bHorz != FALSE)))
			AlignControlBars();

	m_bParentSizing = FALSE;

	return bHorz? CSize(max(m_szMinHorz.cx, m_szHorz.cx),max(m_szMinHorz.cy, m_szHorz.cy)):CSize(max(m_szMinVert.cx, m_szVert.cx),max(m_szMinVert.cy, m_szVert.cy));
}

CSize CControlBarEx::CalcDynamicLayout(int nLength, DWORD dwMode)
{
	if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
	{
		if (nLength == -1)
			m_bParentSizing = TRUE;

		return CControlBar::CalcDynamicLayout(nLength, dwMode);
	}

	if (dwMode & LM_MRUWIDTH) return m_szFloat;
	if (dwMode & LM_COMMIT) return m_szFloat; // already committed

	// check for dialgonal resizing hit test
	int nHitTest = m_pDockContext->m_nHitTest;
	if (IsFloating() && (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT || nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT))
	{
		CPoint ptCursor;
		::GetCursorPos(&ptCursor);

		CRect rFrame, rBar;
		GetParentFrame()->GetWindowRect(&rFrame);
		GetWindowRect(&rBar);
		
		if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
		{
			m_szFloat.cx = rFrame.left + rBar.Width() - ptCursor.x;
			m_pDockContext->m_rectFrameDragHorz.left = 	min(ptCursor.x, rFrame.left + rBar.Width() - m_szMinFloat.cx);
		}

		if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
		{
			m_szFloat.cy = rFrame.top + rBar.Height() - ptCursor.y;
			m_pDockContext->m_rectFrameDragHorz.top = min(ptCursor.y, rFrame.top + rBar.Height() - m_szMinFloat.cy);
		}

		if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
			m_szFloat.cx = rBar.Width() + ptCursor.x - rFrame.right;

		if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
			m_szFloat.cy = rBar.Height() + ptCursor.y - rFrame.bottom;
	}
	else
	{
		if (dwMode & LM_LENGTHY)
			m_szFloat.cy = nLength;
		else
			m_szFloat.cx = nLength;
	}

	m_szFloat.cx = max(m_szFloat.cx, m_szMinFloat.cx);
	m_szFloat.cy = max(m_szFloat.cy, m_szMinFloat.cy);

	return m_szFloat;
}

void CControlBarEx::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
	// force non-client recalc if moved or resized
	lpwndpos->flags |= SWP_FRAMECHANGED;

	CControlBar::OnWindowPosChanging(lpwndpos);

	// find on which side are we docked
	m_nDockBarID = GetParent()->GetDlgCtrlID();

	if (!IsFloating())
		if (lpwndpos->flags & SWP_SHOWWINDOW)
			m_bKeepSize = TRUE;
}

/////////////////////////////////////////////////////////////////////////
// Mouse Handling
//
void CControlBarEx::OnLButtonDown(UINT nFlags, CPoint point)
{
	if (m_pDockBar != NULL)
	{
		// start the drag
		ASSERT(m_pDockContext != NULL);
		ClientToScreen(&point);
		m_pDockContext->StartDrag(point);
	}
	else
		CWnd::OnLButtonDown(nFlags, point);
}

void CControlBarEx::OnLButtonDblClk(UINT nFlags, CPoint point)
{

	if (m_pDockBar != NULL)
	{
		// toggle docking
		ASSERT(m_pDockContext != NULL);
		m_pDockContext->ToggleDocking();
	}
	else

		CWnd::OnLButtonDblClk(nFlags, point);

}

void CControlBarEx::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{

	UNUSED_ALWAYS(point);

	if (m_bTracking || IsFloating())
		return;

	if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
		StartTracking(nHitTest, point); // sizing edge hit

}

void CControlBarEx::OnNcLButtonUp(UINT nHitTest, CPoint point) 
{

	UNUSED_ALWAYS(point);
	if (nHitTest == HTCLOSE)
	   m_pDockSite->ShowControlBar(this, FALSE, FALSE); // hide

}

void CControlBarEx::OnLButtonUp(UINT nFlags, CPoint point)
{

	if (m_bTracking)
		StopTracking();

	CControlBar::OnLButtonUp(nFlags, point);
}

void CControlBarEx::OnRButtonDown(UINT nFlags, CPoint point)
{

	if (m_bTracking)
		StopTracking();

	CControlBar::OnRButtonDown(nFlags, point);
}

void CControlBarEx::OnMouseMove(UINT nFlags, CPoint point)
{

	if (m_bTracking)
	{
		CPoint ptScreen = point;
		ClientToScreen(&ptScreen);

		OnTrackUpdateSize(ptScreen);
	}

	CControlBar::OnMouseMove(nFlags, point);
}

void CControlBarEx::OnCaptureChanged(CWnd *pWnd)
{

	if (m_bTracking && (pWnd != this))
		StopTracking();

	CControlBar::OnCaptureChanged(pWnd);
}

void CControlBarEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
	UNUSED_ALWAYS(bCalcValidRects);

	if (IsFloating())
	{
		CFrameWnd* pFrame = GetParentFrame();
		if (pFrame != NULL && pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
		{
			DWORD dwStyle = ::GetWindowLong(pFrame->m_hWnd, GWL_STYLE);
			if ((dwStyle & MFS_4THICKFRAME) != 0)
			{
				pFrame->ModifyStyle(MFS_4THICKFRAME, 0); // clear
				GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
			}
		}
	}

	// compute the the client area
	m_dwSCBStyle &= ~CBRS_BORDER_ALL;

	// add resizing edges between bars on the same row
	if (!IsFloating() && m_pDockBar != NULL)
	{
		CSCBArray arrSCBars;
		int nThis;
		GetRowSizingBars(arrSCBars, nThis);

		BOOL bHorz = IsHorzDocked();
		if (nThis > 0)
			m_dwSCBStyle |= bHorz ? CBRS_BORDER_LEFT : CBRS_BORDER_TOP;

		if (nThis < arrSCBars.GetUpperBound())
			m_dwSCBStyle |= bHorz ? CBRS_BORDER_RIGHT : CBRS_BORDER_BOTTOM;
	}

	NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID);
}

void CControlBarEx::NcCalcClient(LPRECT pRc, UINT nDockBarID)
{

	CRect rc(pRc);

	rc.DeflateRect(3, 5, 3, 3);
	if (nDockBarID != AFX_IDW_DOCKBAR_FLOAT)
		rc.DeflateRect(2, 0, 2, 2);

	switch(nDockBarID)
	{
	case AFX_IDW_DOCKBAR_TOP:
		m_dwSCBStyle |= CBRS_BORDER_BOTTOM;
		break;
	case AFX_IDW_DOCKBAR_BOTTOM:
		m_dwSCBStyle |= CBRS_BORDER_TOP;
		break;
	case AFX_IDW_DOCKBAR_LEFT:
		m_dwSCBStyle |= CBRS_BORDER_RIGHT;
		break;
	case AFX_IDW_DOCKBAR_RIGHT:
		m_dwSCBStyle |= CBRS_BORDER_LEFT;
		break;
	}

	// make room for edges only if they will be painted
	rc.DeflateRect(
			(m_dwSCBStyle & CBRS_BORDER_LEFT) ? m_cxEdge : 0,
			(m_dwSCBStyle & CBRS_BORDER_TOP) ? m_cxEdge : 0,
			(m_dwSCBStyle & CBRS_BORDER_RIGHT) ? m_cxEdge : 0,
			(m_dwSCBStyle & CBRS_BORDER_BOTTOM) ? m_cxEdge : 0);
	
	if ( !IsFloating() )
	{
		switch ( nDockBarID )
		{
		case AFX_IDW_DOCKBAR_TOP:
			m_biHide.Move(CPoint(m_cyGripper/2-2,5));
			rc.DeflateRect(m_cyGripper, 0, 0, 0);
			break;
		case AFX_IDW_DOCKBAR_BOTTOM:
			m_biHide.Move(CPoint(m_cyGripper/2-2,5+m_cxEdge));
			rc.DeflateRect(m_cyGripper, 0, 0, 0);
			break;
		case AFX_IDW_DOCKBAR_LEFT:
			m_biHide.Move(CPoint(rc.Width()-m_cxEdge,m_cyGripper/2-2));
			rc.DeflateRect(0, m_cyGripper, 0, 0);
			break;
		case AFX_IDW_DOCKBAR_RIGHT:
			m_biHide.Move(CPoint(rc.Width(),m_cyGripper/2-2));
			rc.DeflateRect(0, m_cyGripper, 0, 0);
			break;
		}
	}

	*pRc = rc;

}

void CControlBarEx::OnNcPaint()
{
	// get window DC that is clipped to the non-client area
	CWindowDC dc(this);

	CRect rcClient, rcBar;
	GetClientRect(rcClient);
	ClientToScreen(rcClient);
	GetWindowRect(rcBar);
	rcClient.OffsetRect(-rcBar.TopLeft());
	rcBar.OffsetRect(-rcBar.TopLeft());

	CDC mdc;
	mdc.CreateCompatibleDC(&dc);
	
	CBitmap bm;
	bm.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height());
	CBitmap* pOldBm = mdc.SelectObject(&bm);

	// draw borders in non-client area
	CRect rcDraw = rcBar;
	DrawBorders(&mdc, rcDraw);

	// erase the NC background
	mdc.FillRect(rcDraw, CBrush::FromHandle(
		(HBRUSH) GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));

	CRect rcEdge; // paint the sizing edges
	for (int i = 0; i < 4; i++)
		if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
			mdc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
				::GetSysColor(COLOR_BTNSHADOW));

	if ( !IsFloating() )
		NcPaintGripper(&mdc, rcClient);

	// client area is not our bussiness :)
	dc.IntersectClipRect(rcBar);
	dc.ExcludeClipRect(rcClient);

	dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &mdc, 0, 0, SRCCOPY);

	ReleaseDC(&dc);

	mdc.SelectObject(pOldBm);
	bm.DeleteObject();
	mdc.DeleteDC();
}

void CControlBarEx::NcPaintGripper(CDC* pDC, CRect rcClient)
{

	CRect gripper = rcClient;
	CRect rcbtn = m_biHide.GetRect();
	BOOL bHorz = IsHorzDocked();

	gripper.DeflateRect(1, 1);
	if (bHorz)
	{	// gripper at left
		gripper.left -= m_cyGripper;
		gripper.right = gripper.left + 3;
		gripper.top = rcbtn.bottom + 3;
	}
	else
	{	// gripper at top
		gripper.top -= m_cyGripper;
		gripper.bottom = gripper.top + 3;
		gripper.right = rcbtn.left - 3;
	}

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

	gripper.OffsetRect(bHorz ? 4 : 0, bHorz ? 0 : 4);

⌨️ 快捷键说明

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