📄 sizecbar.cpp
字号:
// sizecbar.cpp : implementation file
//
#include "stdafx.h"
#include "sizecbar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar
IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
CSizingControlBar::CSizingControlBar()
{
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;
}
CSizingControlBar::~CSizingControlBar()
{
}
BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
//{{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
ON_MESSAGE(WM_SETTEXT, OnSetText)
END_MESSAGE_MAP()
// old creation method, still here for compatibility reasons
BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
CSize sizeDefault, BOOL bHasGripper,
UINT nID, DWORD dwStyle)
{
UNUSED_ALWAYS(bHasGripper);
m_szHorz = m_szVert = m_szFloat = sizeDefault;
return Create(lpszWindowName, pParentWnd, nID, dwStyle);
}
// preffered creation method
BOOL CSizingControlBar::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)));
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
if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
CRect(0, 0, 0, 0), pParentWnd, nID))
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar operations
#if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
void CSizingControlBar::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 CSCBDockContext(this);
// permanently wire the bar's owner to its current parent
if (m_hWndOwner == NULL)
m_hWndOwner = ::GetParent(m_hWnd);
}
#endif
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar message handlers
int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (baseCSizingControlBar::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);
// uncomment this line if you want raised borders
// m_dwSCBStyle |= SCBS_SHOWEDGES;
return 0;
}
LRESULT CSizingControlBar::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 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
ASSERT(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_szHorz.cy);
else
return 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;
if (bHorz)
return CSize(max(m_szMinHorz.cx, m_szHorz.cx),
max(m_szMinHorz.cy, m_szHorz.cy));
return CSize(max(m_szMinVert.cx, m_szVert.cx),
max(m_szMinVert.cy, m_szVert.cy));
}
CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
{
if (nLength == -1)
m_bParentSizing = TRUE;
return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
}
if (dwMode & LM_MRUWIDTH) return m_szFloat;
if (dwMode & LM_COMMIT) return m_szFloat; // already committed
#ifndef _SCB_REPLACE_MINIFRAME
// 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
#endif //_SCB_REPLACE_MINIFRAME
((dwMode & LM_LENGTHY) ? m_szFloat.cy : 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 CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
// force non-client recalc if moved or resized
lpwndpos->flags |= SWP_FRAMECHANGED;
baseCSizingControlBar::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
ASSERT(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
ASSERT(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();
baseCSizingControlBar::OnLButtonUp(nFlags, point);
}
void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
{
if (m_bTracking)
StopTracking();
baseCSizingControlBar::OnRButtonDown(nFlags, point);
}
void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bTracking)
{
CPoint ptScreen = point;
ClientToScreen(&ptScreen);
OnTrackUpdateSize(ptScreen);
}
baseCSizingControlBar::OnMouseMove(nFlags, point);
}
void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
{
if (m_bTracking && (pWnd != this))
StopTracking();
baseCSizingControlBar::OnCaptureChanged(pWnd);
}
void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
NCCALCSIZE_PARAMS FAR* lpncsp)
{
UNUSED_ALWAYS(bCalcValidRects);
#ifndef _SCB_REPLACE_MINIFRAME
// Enable diagonal resizing for floating miniframe
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);
}
}
}
#endif _SCB_REPLACE_MINIFRAME
// 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::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 |= 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_cxEdge : 0,
(m_dwSCBStyle & SCBS_EDGETOP) ? m_cxEdge : 0,
(m_dwSCBStyle & SCBS_EDGERIGHT) ? m_cxEdge : 0,
(m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_cxEdge : 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -