📄 sizingcontrolbar.cpp
字号:
//
// FileName: SizingControlBar.cpp
// anli.wei 整理完成
// Copyright (C) 2004 Spreadtrum Corporation
// All rights reserved.
#include "stdafx.h"
#include "SizingControlBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar
IMPLEMENT_DYNAMIC(CSizingControlBar, CControlBar);
CSizingControlBar::CSizingControlBar() : m_nMargin(4)
{
m_bTracking = FALSE;
m_bKeepSize = FALSE;
m_bParentSizing = FALSE;
m_bDragShowContent = FALSE;
m_nDockBarID = 0;
m_dwSCBStyle = 0;
m_sizeHorz = CSize(200, 200);
m_sizeVert = CSize(200, 200);
m_sizeFloat = CSize(200, 200);
m_sizeMinHorz = CSize(64, 32);
m_sizeMinVert = CSize(32, 32);
m_sizeMinFloat = CSize(64, 32);
m_hHorzCursor = NULL;
m_hVertCursor = NULL;
m_pActiveWnd = NULL;
}
CSizingControlBar::~CSizingControlBar()
{
}
BEGIN_MESSAGE_MAP(CSizingControlBar, CControlBar)
//{{AFX_MSG_MAP(CSizingControlBar)
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_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_NCMOUSEMOVE()
ON_WM_NCHITTEST()
ON_WM_CLOSE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CSizingControlBar::Create( LPCTSTR lpszWindowName, CWnd* pParentWnd,
const CSize &sizeDefault, UINT nID,
BOOL bHasGripper /* = FALSE */,
DWORD dwStyle /* = WS_CHILD | WS_VISIBLE | CBRS_TOP*/ )
{
m_sizeHorz = m_sizeVert = m_sizeFloat = sizeDefault;
return Create(lpszWindowName, pParentWnd, nID, dwStyle);
}
BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
UINT nID, DWORD dwStyle)
{
// must have a parent
_ASSERTE( pParentWnd != NULL );
ASSERT_VALID( pParentWnd );
// cannot be both fixed and dynamic
// (CBRS_SIZE_DYNAMIC is used for resizng when floating)
_ASSERTE( !((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 strClassName = ::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
if( !CWnd::Create(strClassName, lpszWindowName, dwStyle,
CRect(0, 0, 0, 0), pParentWnd, nID) )
{
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar message handlers
int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CControlBar::OnCreate(lpCreateStruct) == -1)
return -1;
m_dwSCBStyle |= SCBS_SHOWEDGES;
return 0;
}
const BOOL CSizingControlBar::IsFloating() const
{
return ( !IsHorzDocked() && !IsVertDocked() );
}
const BOOL CSizingControlBar::IsHorzDocked() const
{
return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
}
const BOOL CSizingControlBar::IsVertDocked() const
{
return ( m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT );
}
const BOOL CSizingControlBar::IsSideTracking() const
{
// don't call this when not tracking
_ASSERTE( m_bTracking && !IsFloating() );
return ( m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ? IsHorzDocked() : IsVertDocked();
}
CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
if (bStretch) // the bar is stretched (is not the child of a dockbar)
{
if (bHorz)
return CSize(32767, m_sizeHorz.cy);
else
return CSize(m_sizeVert.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;
if (bHorz)
return CSize(max(m_sizeMinHorz.cx, m_sizeHorz.cx),
max(m_sizeMinHorz.cy, m_sizeHorz.cy));
return CSize(max(m_sizeMinVert.cx, m_sizeVert.cx),
max(m_sizeMinVert.cy, m_sizeVert.cy));
}
CSize CSizingControlBar::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_sizeFloat;
if (dwMode & LM_COMMIT) return m_sizeFloat; // 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 rcFrame, rcBar;
GetParentFrame()->GetWindowRect(&rcFrame);
GetWindowRect(&rcBar);
if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
{
m_sizeFloat.cx = rcFrame.left + rcBar.Width() - ptCursor.x;
m_pDockContext->m_rectFrameDragHorz.left =
min(ptCursor.x, rcFrame.left + rcBar.Width() - m_sizeMinFloat.cx);
}
if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
{
m_sizeFloat.cy = rcFrame.top + rcBar.Height() - ptCursor.y;
m_pDockContext->m_rectFrameDragHorz.top =
min(ptCursor.y, rcFrame.top + rcBar.Height() - m_sizeMinFloat.cy);
}
if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
m_sizeFloat.cx = rcBar.Width() + ptCursor.x - rcFrame.right;
if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
m_sizeFloat.cy = rcBar.Height() + ptCursor.y - rcFrame.bottom;
}
else
{
((dwMode & LM_LENGTHY) ? m_sizeFloat.cy : m_sizeFloat.cx) = nLength;
}
m_sizeFloat.cx = max(m_sizeFloat.cx, m_sizeMinFloat.cx);
m_sizeFloat.cy = max(m_sizeFloat.cy, m_sizeMinFloat.cy);
return m_sizeFloat;
}
void CSizingControlBar::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 CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
{
if(m_pDockBar != NULL)
{
// start the drag
_ASSERTE(m_pDockContext != NULL);
ClientToScreen(&point);
m_pDockContext->StartDrag(point);
}
else
{
CWnd::OnLButtonDown(nFlags, point);
}
}
void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (m_pDockBar != NULL)
{
// toggle docking
_ASSERTE(m_pDockContext != NULL);
m_pDockContext->ToggleDocking();
}
else
{
CWnd::OnLButtonDblClk(nFlags, point);
}
}
void CSizingControlBar::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 CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bTracking)
{
StopTracking();
}
else
{
CControlBar::OnLButtonUp(nFlags, point);
}
}
void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
{
if (m_bTracking)
StopTracking();
CControlBar::OnRButtonDown(nFlags, point);
}
void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bTracking)
{
CPoint ptScreen = point;
ClientToScreen(&ptScreen);
OnTrackUpdateSize(ptScreen);
}
CControlBar::OnMouseMove(nFlags, point);
}
void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
{
if (m_bTracking && (pWnd != this))
StopTracking();
CControlBar::OnCaptureChanged(pWnd);
}
void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
NCCALCSIZE_PARAMS FAR* lpncsp)
{
UNUSED_ALWAYS(bCalcValidRects);
// compute the the client area
m_dwSCBStyle &= ~SCBS_EDGEALL;
// 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 ? SCBS_EDGELEFT : SCBS_EDGETOP;
if (nThis < arrSCBars.GetUpperBound())
m_dwSCBStyle |= bHorz ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM;
}
NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID);
}
void CSizingControlBar::NcPaintGripper(CDC* pDC, LPCRECT pRect)
{
UNUSED_ALWAYS(pDC);
UNUSED_ALWAYS(pRect);
}
void CSizingControlBar::NcCalcClient(LPRECT pRect, UINT nDockBarID)
{
_ASSERTE( pRect != NULL );
CRect rc(pRect);
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 |= SCBS_EDGEBOTTOM;
break;
case AFX_IDW_DOCKBAR_BOTTOM:
m_dwSCBStyle |= SCBS_EDGETOP;
break;
case AFX_IDW_DOCKBAR_LEFT:
m_dwSCBStyle |= SCBS_EDGERIGHT;
break;
case AFX_IDW_DOCKBAR_RIGHT:
m_dwSCBStyle |= SCBS_EDGELEFT;
break;
}
// make room for edges only if they will be painted
if (m_dwSCBStyle & SCBS_SHOWEDGES)
{
rc.DeflateRect( (m_dwSCBStyle & SCBS_EDGELEFT) ? m_nMargin : 0,
(m_dwSCBStyle & SCBS_EDGETOP) ? m_nMargin : 0,
(m_dwSCBStyle & SCBS_EDGERIGHT) ? m_nMargin : 0,
(m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_nMargin : 0 );
}
*pRect = rc;
}
void CSizingControlBar::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 dcMem;
VERIFY( dcMem.CreateCompatibleDC(&dc) );
CBitmap bmp;
VERIFY( bmp.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height()) );
CBitmap* pOldBm = dcMem.SelectObject(&bmp);
// draw borders in non-client area
CRect rcDraw = rcBar;
DrawBorders(&dcMem, rcDraw);
// erase the NC background
dcMem.FillRect(rcDraw,
CBrush::FromHandle((HBRUSH)GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));
if (m_dwSCBStyle & SCBS_SHOWEDGES)
{
CRect rcEdge; // paint the sizing edges
UINT uHitTest;
for (int i = 0; i < 4; i++)
{
uHitTest = GetEdgeHTCode(i);
if (GetEdgeRect(rcBar, uHitTest, rcEdge))
{
if( HTRIGHT == uHitTest || HTBOTTOM == uHitTest )
{
dcMem.Draw3dRect( rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_3DDKSHADOW) );
}
else
{
if( HTLEFT == uHitTest ) rcEdge.right++;
if( HTTOP == uHitTest ) rcEdge.bottom++;
dcMem.DrawEdge( rcEdge, EDGE_RAISED, BF_RECT);
}
}
}
}
NcPaintGripper(&dcMem, rcClient);
// client area is not our bussiness :)
dc.IntersectClipRect(&rcBar);
dc.ExcludeClipRect(&rcClient);
dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &dcMem, 0, 0, SRCCOPY);
ReleaseDC(&dc);
dcMem.SelectObject(pOldBm);
bmp.DeleteObject();
dcMem.DeleteDC();
}
void CSizingControlBar::OnPaint()
{
// overridden to skip border painting based on clientrect
// don't delete or annotate CPaintDC dc(this); !!!!! anli.wei
CPaintDC dc(this);
}
void CSizingControlBar::OnSize(UINT nType, int cx, int cy)
{
UNUSED_ALWAYS(nType);
// TODO: Add your message handler code here
if( m_pActiveWnd != NULL )
{
m_pActiveWnd->MoveWindow(0, 0, cx, cy);
}
}
UINT CSizingControlBar::OnNcHitTest(CPoint point)
{
CRect rcBar, rcEdge;
GetWindowRect(rcBar);
if (!IsFloating())
{
UINT uHitTest = 0;
for (int i = 0; i < 4; i++)
{
uHitTest = GetEdgeHTCode(i);
if (GetEdgeRect(rcBar, uHitTest, rcEdge))
{
if (rcEdge.PtInRect(point))
{
if( m_hHorzCursor != NULL &&
(HTLEFT == uHitTest || HTRIGHT == uHitTest) )
{
SetCursor(m_hHorzCursor);
}
if( m_hVertCursor != NULL &&
(HTTOP == uHitTest || HTBOTTOM == uHitTest) )
{
SetCursor(m_hVertCursor);
}
return uHitTest;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -