📄 controlbarex.cpp
字号:
pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_BTNSHADOW));
m_biHide.Paint(pDC);
}
void CControlBarEx::OnPaint()
{
// overridden to skip border painting based on clientrect
CPaintDC dc(this);
}
UINT CControlBarEx::OnNcHitTest(CPoint point)
{
CRect rcBar, rcEdge;
GetWindowRect(rcBar);
if (!IsFloating())
for (int i = 0; i < 4; i++)
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
if (rcEdge.PtInRect(point))
return GetEdgeHTCode(i);
CRect rc = m_biHide.GetRect();
rc.OffsetRect(rcBar.TopLeft());
if (rc.PtInRect(point))
return HTCLOSE;
return HTCLIENT;
}
void CControlBarEx::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
CControlBar::OnSettingChange(uFlags, lpszSection);
m_bDragShowContent = FALSE;
::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
&m_bDragShowContent, 0); // update
}
void CControlBarEx::OnSize(UINT nType, int cx, int cy)
{
CWnd *pWnd = GetWindow(GW_CHILD);
if ( pWnd != NULL )
pWnd->MoveWindow(0,0,cx,cy);
}
void CControlBarEx::OnClose()
{
// do nothing: protection against accidentally destruction by the
// child control (i.e. if user hits Esc in a child editctrl)
}
/////////////////////////////////////////////////////////////////////////
// CControlBarEx implementation helpers
void CControlBarEx::StartTracking(UINT nHitTest, CPoint point)
{
SetCapture();
// make sure no updates are pending
if (!m_bDragShowContent)
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
m_htEdge = nHitTest;
m_bTracking = TRUE;
BOOL bHorz = IsHorzDocked();
BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
m_nTrackPosOld = bHorzTracking ? point.x : point.y;
CRect rcBar, rcEdge;
GetWindowRect(rcBar);
GetEdgeRect(rcBar, m_htEdge, rcEdge);
m_nTrackEdgeOfs = m_nTrackPosOld -
(bHorzTracking ? rcEdge.CenterPoint().x : rcEdge.CenterPoint().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_szMinHorz.cy : m_szMinVert.cx;
for (int i = 0; i < arrSCBars.GetSize(); i++)
nMinWidth = max(nMinWidth, bHorz ?
arrSCBars[i]->m_szMinHorz.cy :
arrSCBars[i]->m_szMinVert.cx);
int nExcessWidth = (bHorz ? m_szHorz.cy : m_szVert.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++;
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
CControlBarEx* pBar = arrSCBars[i];
int nExcessWidth = bHorz ?
pBar->m_szHorz.cx - pBar->m_szMinHorz.cx :
pBar->m_szVert.cy - pBar->m_szMinVert.cy;
if (i < nThis)
m_nTrackPosMin -= nExcessWidth;
else
m_nTrackPosMax += nExcessWidth;
}
}
OnTrackInvertTracker(); // draw tracker
}
void CControlBarEx::StopTracking()
{
OnTrackInvertTracker(); // erase tracker
m_bTracking = FALSE;
ReleaseCapture();
m_pDockSite->DelayRecalcLayout();
}
void CControlBarEx::OnTrackUpdateSize(CPoint& point)
{
ASSERT(!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
OnTrackInvertTracker(); // erase tracker
m_nTrackPosOld = nTrackPos;
BOOL bHorz = IsHorzDocked();
CSize sizeNew = bHorz ? m_szHorz : m_szVert;
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())
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
CControlBarEx* pBar = arrSCBars[i];
// make same width (or height)
(bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.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);
CControlBarEx* pBar = arrSCBars[nGrowingBar];
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.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))
{
CControlBarEx* pBar = arrSCBars[i];
int nDeltaT = min(nDelta,
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -
(bHorz ? pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy));
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= nDeltaT;
nDelta -= nDeltaT;
}
}
OnTrackInvertTracker(); // redraw tracker at new pos
if (m_bDragShowContent)
m_pDockSite->DelayRecalcLayout();
}
void CControlBarEx::OnTrackInvertTracker()
{
ASSERT(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_nTrackEdgeOfs;
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 CControlBarEx::GetEdgeRect(CRect rcWnd, UINT nHitTest,
CRect& rcEdge)
{
rcEdge = rcWnd;
rcEdge.DeflateRect(1, 1);
BOOL bHorz = IsHorzDocked();
switch (nHitTest)
{
case HTLEFT:
if (!(m_dwSCBStyle & CBRS_BORDER_LEFT)) return FALSE;
rcEdge.right = rcEdge.left + m_cxEdge+1;
if ( bHorz )
rcEdge.bottom -= m_cxEdge;
break;
case HTTOP:
if (!(m_dwSCBStyle & CBRS_BORDER_TOP)) return FALSE;
rcEdge.bottom = rcEdge.top + m_cxEdge+1;
if ( !bHorz )
rcEdge.right -= m_cxEdge;
break;
case HTRIGHT:
if (!(m_dwSCBStyle & CBRS_BORDER_RIGHT)) return FALSE;
rcEdge.left = rcEdge.right - m_cxEdge;
if ( bHorz )
rcEdge.bottom -= m_cxEdge;
break;
case HTBOTTOM:
if (!(m_dwSCBStyle & CBRS_BORDER_BOTTOM)) return FALSE;
rcEdge.top = rcEdge.bottom - m_cxEdge-1;
if ( !bHorz )
rcEdge.right -= m_cxEdge;
break;
default:
ASSERT(FALSE); // invalid hit test code
}
return TRUE;
}
UINT CControlBarEx::GetEdgeHTCode(int nEdge)
{
if (nEdge == 0) return HTLEFT;
if (nEdge == 1) return HTTOP;
if (nEdge == 2) return HTRIGHT;
if (nEdge == 3) return HTBOTTOM;
ASSERT(FALSE); // invalid edge code
return HTNOWHERE;
}
void CControlBarEx::GetRowInfo(int& nFirst, int& nLast, int& nThis)
{
ASSERT_VALID(m_pDockBar); // verify bounds
nThis = m_pDockBar->FindBar(this);
ASSERT(nThis != -1);
int i, nBars = m_pDockBar->m_arrBars.GetSize();
// 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;
for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
if (m_pDockBar->m_arrBars[i] == NULL)
nLast = i - 1;
ASSERT((nLast != -1) && (nFirst != -1));
}
void CControlBarEx::GetRowSizingBars(CSCBArray& arrSCBars)
{
int nThis; // dummy
GetRowSizingBars(arrSCBars, nThis);
}
void CControlBarEx::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
{
arrSCBars.RemoveAll();
int nFirstT, nLastT, nThisT;
GetRowInfo(nFirstT, nLastT, nThisT);
nThis = -1;
for (int i = nFirstT; i <= nLastT; i++)
{
CControlBarEx* pBar =
(CControlBarEx*) m_pDockBar->m_arrBars[i];
if (HIWORD(pBar) == 0) continue; // placeholder
if (!pBar->IsVisible()) continue;
if (pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx)))
{
if (pBar == this)
nThis = arrSCBars.GetSize();
arrSCBars.Add(pBar);
}
}
}
BOOL CControlBarEx::NegotiateSpace(int nLengthTotal, BOOL bHorz)
{
int nFirst, nLast, nThis;
GetRowInfo(nFirst, nLast, nThis);
int nLengthAvail = nLengthTotal;
int nLengthActual = 0;
int nLengthMin = 2;
int nWidthMax = 0;
CControlBarEx* pBar;
for (int i = nFirst; i <= nLast; i++)
{
pBar = (CControlBarEx*) m_pDockBar->m_arrBars[i];
if (HIWORD(pBar) == 0) continue; // placeholder
if (!pBar->IsVisible()) continue;
BOOL bIsSizingBar = pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx));
int nLengthBar; // minimum length of the bar
if (bIsSizingBar)
nLengthBar = bHorz ? pBar->m_szMinHorz.cx - 2 : pBar->m_szMinVert.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_szHorz.cx = m_szMinHorz.cx;
else
m_szVert.cy = m_szMinVert.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_szHorz.cx - 2 : pBar->m_szVert.cy - 2;
nWidthMax = max(nWidthMax, bHorz ? pBar->m_szHorz.cy :pBar->m_szVert.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)
{
ASSERT(arrSCBars[0] == this);
if (nDelta == 0)
return TRUE;
m_bKeepSize = FALSE;
(bHorz ? m_szHorz.cx : m_szVert.cy) += nDelta;
return TRUE;
}
// make all the bars the same width
for (i = 0; i < nNumBars; i++)
if (bHorz)
arrSCBars[i]->m_szHorz.cy = nWidthMax;
else
arrSCBars[i]->m_szVert.cx = nWidthMax;
// distribute the difference between the bars,
// but don't shrink them below their minsizes
while (nDelta != 0)
{
int nDeltaOld = nDelta;
for (i = 0; i < nNumBars; i++)
{
pBar = arrSCBars[i];
int nLMin = bHorz ?
pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy;
int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;
if ((nL == nLMin) && (nDelta < 0) || // already at min length
pBar->m_bKeepSize) // or wants to keep its size
continue;
// sign of nDelta
int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.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 CControlBarEx::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);
for (int i = nFirst; i <= nLast; i++)
{
CControlBarEx* pBar =
(CControlBarEx*) m_pDockBar->m_arrBars[i];
if (HIWORD(pBar) == 0) continue; // placeholder
if (!pBar->IsVisible()) continue;
pBar->GetWindowRect(&rc);
rc.OffsetRect(-rcDock.TopLeft());
if (pBar->IsKindOf(RUNTIME_CLASS(CControlBarEx)))
rc = CRect(rc.TopLeft(),
bHorz ? pBar->m_szHorz : pBar->m_szVert);
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 CControlBarEx::OnUpdateCmdUI(CFrameWnd* pTarget,BOOL bDisableIfNoHndler)
{
if ( IsFloating() )
return;
BOOL bNeedPaint = FALSE;
CPoint pt;
::GetCursorPos(&pt);
BOOL bHit = (OnNcHitTest(pt) == HTCLOSE);
BOOL bLButtonDown = (::GetKeyState(VK_LBUTTON) < 0);
BOOL bWasPushed = m_biHide.bPushed;
m_biHide.bPushed = bHit && bLButtonDown;
BOOL bWasRaised = m_biHide.bRaised;
m_biHide.bRaised = bHit && !bLButtonDown;
bNeedPaint |= (m_biHide.bPushed ^ bWasPushed) ||
(m_biHide.bRaised ^ bWasRaised);
if (bNeedPaint)
SendMessage(WM_NCPAINT);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -