📄 controlbarex.cpp
字号:
#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 + -