📄 bcgsizingcontrolbar.cpp
字号:
}
ReleaseDC(&dc);
}
void CBCGSizingControlBar::OnPaint()
{
// overridden to skip border painting based on clientrect
CPaintDC dc(this);
}
UINT CBCGSizingControlBar::OnNcHitTest(CPoint point)
{
CRect rcBar, rcEdge;
GetWindowRect(rcBar);
// By Erwin Tratar
if (IsFloating()) {
for (int i = 0; i < 4; i++)
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
if (rcEdge.PtInRect(point)) return GetEdgeHTCode(i);
return CControlBar::OnNcHitTest(point);
}
////////
for (int i = 0; i < 4; i++)
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
if (rcEdge.PtInRect(point)) return GetEdgeHTCode(i);
for (i = 0; i < CBCGSIZINGCONTROLBAR_BUTTONS_NUM; i ++)
{
CSCBButton& btn = m_Buttons [i];
CRect rc = btn.GetRect();
rc.OffsetRect(rcBar.TopLeft());
if (rc.PtInRect(point))
{
return btn.m_nHit;
}
}
// Maybe on caption?
CRect rcClient;
GetClientRect(rcClient);
ClientToScreen(&rcClient);
if( !rcClient.PtInRect(point))
return HTCAPTION;
return HTCLIENT;
}
/////////////////////////////////////////////////////////////////////////
// CBCGSizingControlBar implementation helpers
void CBCGSizingControlBar::StartTracking(UINT nHitTest)
{
SetCapture();
// make sure no updates are pending
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
BOOL bHorz = IsHorzDocked();
m_szOld = bHorz ? m_szHorz : m_szVert;
CRect rc;
GetWindowRect(&rc);
m_ptOld = ::GetMessagePos();
ScreenToClient(&m_ptOld);
m_htEdge = nHitTest;
m_bTracking = TRUE;
CSCBArray arrSCBars;
GetRowSizingBars(arrSCBars);
// compute the minsize as the max minsize of the sizing bars on row
m_szMinT = m_szMin;
for (int i = 0; i < arrSCBars.GetSize(); i++)
if (bHorz)
m_szMinT.cy = max(m_szMinT.cy, arrSCBars[i]->m_szMin.cy);
else
m_szMinT.cx = max(m_szMinT.cx, arrSCBars[i]->m_szMin.cx);
if (!IsSideTracking())
{
// the control bar cannot grow with more than the size of
// remaining client area of the mainframe
m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
reposQuery, &rc, NULL, TRUE);
m_pDockSite->SendMessage(WM_IDLEUPDATECMDUI);
m_szMaxT = m_szOld + rc.Size() - CSize(4, 4);
}
else
{
// side tracking: max size is the actual size plus the amount
// the neighbour bar can be decreased to reach its minsize
BOOL bFound = FALSE;
for (int i = 0; i < arrSCBars.GetSize (); i++)
{
if (arrSCBars [i] == this)
{
bFound = TRUE;
break;
}
}
if (bFound)
{
CBCGSizingControlBar* pBar = arrSCBars[i +
((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)];
m_szMaxT = m_szOld + (bHorz ? pBar->m_szHorz :
pBar->m_szVert) - pBar->m_szMin;
}
}
OnTrackInvertTracker(); // draw tracker
}
void CBCGSizingControlBar::StopTracking()
{
OnTrackInvertTracker(); // erase tracker
m_bTracking = FALSE;
ReleaseCapture();
m_pDockSite->DelayRecalcLayout();
}
void CBCGSizingControlBar::OnTrackUpdateSize(CPoint& point)
{
ASSERT(!IsFloating());
CSize szDelta = point - m_ptOld;
if (szDelta == CSize(0, 0)) return; // no size change
CSize sizeNew = m_szOld;
switch (m_htEdge)
{
case HTLEFT: sizeNew -= CSize(szDelta.cx, 0); break;
case HTTOP: sizeNew -= CSize(0, szDelta.cy); break;
case HTRIGHT: sizeNew += CSize(szDelta.cx, 0); break;
case HTBOTTOM: sizeNew += CSize(0, szDelta.cy); break;
}
// enforce the limits
sizeNew.cx = max(m_szMinT.cx, min(m_szMaxT.cx, sizeNew.cx));
sizeNew.cy = max(m_szMinT.cy, min(m_szMaxT.cy, sizeNew.cy));
BOOL bHorz = IsHorzDocked();
szDelta = sizeNew - (bHorz ? m_szHorz : m_szVert);
OnTrackInvertTracker(); // erase tracker
(bHorz ? m_szHorz : m_szVert) = sizeNew; // save the new size
CSCBArray arrSCBars;
GetRowSizingBars(arrSCBars);
for (int i = 0; i < arrSCBars.GetSize(); i++)
{
CBCGSizingControlBar* pBar = NULL;
if (!IsSideTracking())
{ // track simultaneously
pBar = arrSCBars[i];
ASSERT_VALID (pBar);
(bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
bHorz ? sizeNew.cy : sizeNew.cx;
}
else
{ // adjust the neighbour's size too
if (arrSCBars[i] != this) continue;
pBar = arrSCBars[i +
((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)];
ASSERT_VALID (pBar);
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -=
bHorz ? szDelta.cx : szDelta.cy;
}
}
OnTrackInvertTracker(); // redraw tracker at new pos
}
void CBCGSizingControlBar::OnTrackInvertTracker()
{
ASSERT(m_bTracking);
if (m_pDockBar == NULL)
{
return;
}
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);
rc.OffsetRect(-rcFrame.TopLeft());
CSize sizeNew = bHorz ? m_szHorz : m_szVert;
CSize sizeDelta = sizeNew - m_szOld;
if (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT && m_htEdge == HTTOP ||
m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT && m_htEdge != HTBOTTOM ||
m_nDockBarID == AFX_IDW_DOCKBAR_TOP && m_htEdge == HTLEFT ||
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM && m_htEdge != HTRIGHT)
sizeDelta = -sizeDelta;
rc.OffsetRect(sizeDelta);
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 CBCGSizingControlBar::GetEdgeRect(CRect rcWnd, UINT nHitTest,
CRect& rcEdge)
{
if (!IsEdgeVisible (nHitTest))
{
rcEdge.SetRectEmpty ();
return FALSE;
}
rcEdge = rcWnd;
if (m_dwSCBStyle & SCBS_SHOWEDGES)
{
rcEdge.DeflateRect(1, 1);
}
BOOL bHorz = IsHorzDocked();
switch (nHitTest)
{
case HTLEFT:
rcEdge.right = rcEdge.left + m_cxEdge;
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
if (m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM)
{
rcEdge.bottom = rcWnd.bottom + 1;
}
if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
{
rcEdge.top = rcWnd.top - 1;
}
break;
case HTTOP:
rcEdge.bottom = rcEdge.top + m_cxEdge;
rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
if (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT)
{
rcEdge.left = rcWnd.left - 1;
}
if (m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT)
{
rcEdge.right = rcWnd.right + 1;
}
break;
case HTRIGHT:
rcEdge.left = rcEdge.right - m_cxEdge;
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
{
rcEdge.top = rcWnd.top - 1;
}
if (m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM)
{
rcEdge.bottom = rcWnd.bottom + 1;
}
break;
case HTBOTTOM:
rcEdge.top = rcEdge.bottom - m_cxEdge;
rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
if (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT)
{
rcEdge.left = rcWnd.left - 1;
}
if (m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT)
{
rcEdge.right = rcWnd.right + 1;
}
break;
default:
ASSERT(FALSE); // invalid hit test code
}
return TRUE;
}
UINT CBCGSizingControlBar::GetEdgeHTCode(int nEdge)
{
switch (nEdge)
{
case 0: return HTLEFT;
case 1: return HTTOP;
case 2: return HTRIGHT;
case 3: return HTBOTTOM;
}
ASSERT(FALSE); // invalid edge no
return HTNOWHERE;
}
void CBCGSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
{
if (m_pDockBar == NULL)
{
return;
}
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 CBCGSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
{
arrSCBars.RemoveAll();
if (m_pDockBar == NULL)
{
return;
}
int nFirst, nLast, nThis;
GetRowInfo(nFirst, nLast, nThis);
for (int i = nFirst; i <= nLast; i++)
{
CControlBar* pBar = (CControlBar*)m_pDockBar->m_arrBars[i];
if (HIWORD(pBar) == 0) continue; // placeholder
if (!pBar->IsVisible()) continue;
if (FindSizingBar(pBar) >= 0)
arrSCBars.Add((CBCGSizingControlBar*)pBar);
}
}
const int CBCGSizingControlBar::FindSizingBar(CControlBar* pBar) const
{
for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
if (m_arrBars[nPos] == pBar)
return nPos; // got it
return -1; // not found
}
BOOL CBCGSizingControlBar::NegociateSpace(int nLengthAvail, BOOL bHorz)
{
if (m_pDockBar == NULL)
{
return TRUE;
}
ASSERT(bHorz == IsHorzDocked());
int nFirst, nLast, nThis;
GetRowInfo(nFirst, nLast, nThis);
// step 1: subtract the visible fixed bars' lengths
for (int i = nFirst; i <= nLast; i++)
{
CControlBar* pFBar = (CControlBar*)m_pDockBar->m_arrBars[i];
if (HIWORD(pFBar) == 0) continue; // placeholder
if (!pFBar->IsVisible() || (FindSizingBar(pFBar) >= 0)) continue;
CRect rcBar;
pFBar->GetWindowRect(&rcBar);
nLengthAvail -= (bHorz ? rcBar.Width() : rcBar.Height() );
}
CSCBArray arrSCBars;
GetRowSizingBars(arrSCBars);
CBCGSizingControlBar* pBar;
// step 2: compute actual and min lengths; also the common width
int nActualLength = 0;
int nMinLength = 2;
int nWidth = 0;
for (i = 0; i < arrSCBars.GetSize(); i++)
{
pBar = arrSCBars[i];
nActualLength += bHorz ? pBar->m_szHorz.cx :
pBar->m_szVert.cy ;
nMinLength += bHorz ? pBar->m_szMin.cx :
pBar->m_szMin.cy ;
nWidth = max(nWidth, bHorz ? pBar->m_szHorz.cy :
pBar->m_szVert.cx);
}
// step 3: pop the bar out of the row if not enough room
if (nMinLength > nLengthAvail)
{
if (nFirst < nThis || nThis < nLast)
{ // not enough room - create a new row
m_pDockBar->m_arrBars.InsertAt(nLast + 1, this);
m_pDockBar->m_arrBars.InsertAt(nLast + 1, (CControlBar*) NULL);
m_pDockBar->m_arrBars.RemoveAt(nThis);
}
return FALSE;
}
// step 4: make the bars same width
for (i = 0; i < arrSCBars.GetSize(); i++)
{
if (bHorz)
arrSCBars[i]->m_szHorz.cy = nWidth;
else
arrSCBars[i]->m_szVert.cx = nWidth;
}
if (nActualLength == nLengthAvail)
return TRUE; // no change
// step 5: distribute the difference between the bars, but
// don't shrink them below minsize
int nDelta = nLengthAvail - nActualLength;
while (nDelta != 0)
{
int nDeltaOld = nDelta;
for (i = 0; i < arrSCBars.GetSize(); i++)
{
pBar = arrSCBars[i];
int nLMin = bHorz ? pBar->m_szMin.cx : pBar->m_szMin.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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -