📄 sizingcontrolbar.cpp
字号:
return HTCLIENT;
}
void CSizingControlBar::OnClose()
{
// do nothing: protection against accidentally destruction by the
// child control (i.e. if user hits Esc in a child editctrl)
}
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar implementation helpers
void CSizingControlBar::StartTracking(UINT nHitTest, const CPoint &pt)
{
m_pDockSite->LockWindowUpdate();
SetCapture();
// make sure no updates are pending
if(!m_bDragShowContent)
{
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
}
m_bTracking = TRUE;
m_htEdge = nHitTest;
BOOL bHorz = IsHorzDocked();
BOOL bHorzTracking = ( m_htEdge == HTLEFT || m_htEdge == HTRIGHT );
m_nTrackPosOld = bHorzTracking ? pt.x : pt.y;
CRect rcBar, rcEdge;
GetWindowRect(&rcBar);
GetEdgeRect(rcBar, m_htEdge, rcEdge);
CPoint &ptCenter = rcEdge.CenterPoint();
m_nTrackEdgeOffset = m_nTrackPosOld - (bHorzTracking ? ptCenter.x : ptCenter.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_sizeMinHorz.cy : m_sizeMinVert.cx;
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
nMinWidth = max(nMinWidth, bHorz ? arrSCBars[i]->m_sizeMinHorz.cy :
arrSCBars[i]->m_sizeMinVert.cx);
}
int nExcessWidth = (bHorz ? m_sizeHorz.cy : m_sizeVert.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++;
CSizingControlBar * pBar = NULL;
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
pBar = arrSCBars[i];
int nExcessWidth = bHorz ?
pBar->m_sizeHorz.cx - pBar->m_sizeMinHorz.cx :
pBar->m_sizeVert.cy - pBar->m_sizeMinVert.cy;
if (i < nThis)
m_nTrackPosMin -= nExcessWidth;
else
m_nTrackPosMax += nExcessWidth;
}
}
OnInvertTracker(); // draw tracker
}
void CSizingControlBar::StopTracking()
{
OnInvertTracker(); // erase tracker
m_bTracking = FALSE;
ReleaseCapture();
m_pDockSite->DelayRecalcLayout();
m_pDockSite->UnlockWindowUpdate();
}
void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
{
_ASSERTE( !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
OnInvertTracker(); // erase tracker
m_nTrackPosOld = nTrackPos;
BOOL bHorz = IsHorzDocked();
CSize sizeNew = bHorz ? m_sizeHorz : m_sizeVert;
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())
{
CSizingControlBar* pBar = NULL;
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
pBar = arrSCBars[i];
// make same width (or height)
(bHorz ? pBar->m_sizeHorz.cy : pBar->m_sizeVert.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);
CSizingControlBar* pBar = arrSCBars[nGrowingBar];
(bHorz ? pBar->m_sizeHorz.cx : pBar->m_sizeVert.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))
{
pBar = arrSCBars[i];
int nDeltaT = min(nDelta,
(bHorz ? pBar->m_sizeHorz.cx : pBar->m_sizeVert.cy) -
(bHorz ? pBar->m_sizeMinHorz.cx : pBar->m_sizeMinVert.cy));
(bHorz ? pBar->m_sizeHorz.cx : pBar->m_sizeVert.cy) -= nDeltaT;
nDelta -= nDeltaT;
}
}
OnInvertTracker(); // redraw tracker at new pos
if (m_bDragShowContent)
{
m_pDockSite->DelayRecalcLayout();
}
}
void CSizingControlBar::OnInvertTracker()
{
_ASSERTE( 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_nTrackEdgeOffset;
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 CSizingControlBar::GetEdgeRect(const CRect &rcWnd, UINT nHitTest, CRect& rcEdge)
{
rcEdge = rcWnd;
if (m_dwSCBStyle & SCBS_SHOWEDGES)
{
rcEdge.DeflateRect(1, 1);
}
BOOL bHorz = IsHorzDocked();
switch (nHitTest)
{
case HTLEFT:
if ( !(m_dwSCBStyle & SCBS_EDGELEFT) ) return FALSE;
rcEdge.right = rcEdge.left + m_nMargin;
rcEdge.DeflateRect(0, bHorz ? m_nMargin: 0);
break;
case HTTOP:
if ( !(m_dwSCBStyle & SCBS_EDGETOP) ) return FALSE;
rcEdge.bottom = rcEdge.top + m_nMargin;
rcEdge.DeflateRect(bHorz ? 0 : m_nMargin, 0);
break;
case HTRIGHT:
if ( !(m_dwSCBStyle & SCBS_EDGERIGHT) ) return FALSE;
rcEdge.left = rcEdge.right - m_nMargin;
rcEdge.DeflateRect(0, bHorz ? m_nMargin: 0);
break;
case HTBOTTOM:
if ( !(m_dwSCBStyle & SCBS_EDGEBOTTOM) ) return FALSE;
rcEdge.top = rcEdge.bottom - m_nMargin;
rcEdge.DeflateRect(bHorz ? 0 : m_nMargin, 0);
break;
default:
_ASSERTE(FALSE); // invalid hit test code
}
return TRUE;
}
UINT CSizingControlBar::GetEdgeHTCode(int nEdge)
{
switch( nEdge )
{
case 0: return HTLEFT;
case 1: return HTTOP;
case 2: return HTRIGHT;
case 3: return HTBOTTOM;
default:
_ASSERTE(FALSE); // invalid edge code
}
return HTNOWHERE;
}
void CSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
{
_ASSERTE( m_pDockBar != NULL );
ASSERT_VALID(m_pDockBar); // verify bounds
nThis = m_pDockBar->FindBar(this);
_ASSERTE(nThis != -1);
int i = -1;
// 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;
}
}
int nBars = m_pDockBar->m_arrBars.GetSize();
for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
{
if (m_pDockBar->m_arrBars[i] == NULL)
{
nLast = i - 1;
}
}
_ASSERTE( (nLast != -1) && (nFirst != -1) );
}
void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
{
int nThis; // dummy
GetRowSizingBars(arrSCBars, nThis);
}
void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
{
arrSCBars.RemoveAll();
int nFirst, nLast, nThisTmp;
GetRowInfo(nFirst, nLast, nThisTmp);
nThis = -1;
CSizingControlBar* pBar = NULL;
for (int i = nFirst; i <= nLast; i++)
{
pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
if(HIWORD(pBar) == 0 || !pBar->IsVisible() )
{
continue; // placeholder
}
if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
{
if (pBar == this)
{
nThis = arrSCBars.GetSize();
}
arrSCBars.Add(pBar);
}
}
}
BOOL CSizingControlBar::NegotiateSpace(int nLengthTotal, BOOL bHorz)
{
if( bHorz != IsHorzDocked() )
return FALSE;
int nFirst, nLast, nThis;
GetRowInfo(nFirst, nLast, nThis);
int nLengthAvail = nLengthTotal;
int nLengthActual = 0;
int nLengthMin = 2;
int nWidthMax = 0;
CSizingControlBar* pBar = NULL;
for (int i = nFirst; i <= nLast; i++)
{
pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
if( HIWORD(pBar) == 0 || !pBar->IsVisible() )
{
continue; // placeholder
}
BOOL bIsSizingBar = pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar));
int nLengthBar; // minimum length of the bar
if (bIsSizingBar)
{
nLengthBar = bHorz ? pBar->m_sizeMinHorz.cx - 2 : pBar->m_sizeMinVert.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_sizeHorz.cx = m_sizeMinHorz.cx;
else
m_sizeVert.cy = m_sizeMinVert.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_sizeHorz.cx - 2 : pBar->m_sizeVert.cy - 2;
nWidthMax = max(nWidthMax, bHorz ? pBar->m_sizeHorz.cy : pBar->m_sizeVert.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)
{
_ASSERTE( arrSCBars[0] == this );
if (nDelta == 0) return TRUE;
m_bKeepSize = FALSE;
(bHorz ? m_sizeHorz.cx : m_sizeVert.cy) += nDelta;
return TRUE;
}
// make all the bars the same width
for(i = 0; i < nNumBars; i++)
{
if (bHorz)
arrSCBars[i]->m_sizeHorz.cy = nWidthMax;
else
arrSCBars[i]->m_sizeVert.cx = nWidthMax;
}
// distribute the difference between the bars,
// but don't shrink them below their minsizes
for(; nDelta != 0; )
{
int nDeltaOld = nDelta;
for (i = 0; i < nNumBars; i++)
{
pBar = arrSCBars[i];
int nLMin = bHorz ? pBar->m_sizeMinHorz.cx : pBar->m_sizeMinVert.cy;
int nL = bHorz ? pBar->m_sizeHorz.cx : pBar->m_sizeVert.cy;
// already at min length or wants to keep its size
if( (nL == nLMin) && (nDelta < 0) || pBar->m_bKeepSize)
continue;
// sign of nDelta
int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
(bHorz ? pBar->m_sizeHorz.cx : pBar->m_sizeVert.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 CSizingControlBar::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);
CSizingControlBar* pBar = NULL;
for (int i = nFirst; i <= nLast; i++)
{
pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
if (HIWORD(pBar) == 0 || !pBar->IsVisible() )
{
continue; // placeholder
}
pBar->GetWindowRect(&rc);
rc.OffsetRect(-rcDock.TopLeft());
if(pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
{
rc = CRect(rc.TopLeft(), bHorz ? pBar->m_sizeHorz : pBar->m_sizeVert);
}
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 CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
UNUSED_ALWAYS(bDisableIfNoHndler);
UNUSED_ALWAYS(pTarget);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -