void CSizingControlBar::StartTracking(UINT nHitTest) { SetCapture(); // make sure no updates are pending if (!m_bDragShowContent) RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW); BOOL bHorz = IsHorzDocked(); m_szOld = bHorz ? m_szHorz : m_szVert; CRect rc; GetWindowRect(&rc); CRect rcEdge; VERIFY(GetEdgeRect(rc, nHitTest, rcEdge)); m_ptOld = rcEdge.CenterPoint(); 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 = bHorz ? m_szMinHorz : m_szMinVert; for (int i = 0; i < arrSCBars.GetSize(); i++) if (bHorz) m_szMinT.cy = max(m_szMinT.cy, arrSCBars[i]->m_szMinHorz.cy); else m_szMinT.cx = max(m_szMinT.cx, arrSCBars[i]->m_szMinVert.cx); m_szMaxT = m_szOld; 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_szMaxT += 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 for (int i = 0; i < arrSCBars.GetSize(); i++) if (arrSCBars[i] == this) break; CSizingControlBar* pBar = arrSCBars[i + ((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)]; m_szMaxT += (bHorz ? pBar->m_szHorz : pBar->m_szVert) - CSize(pBar->m_szMinHorz.cx, pBar->m_szMinVert.cy); } OnTrackInvertTracker(); // draw tracker }
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; if (!IsFloating() && m_pDockBar != NULL) { CSCBArray arrSCBars; GetRowSizingBars(arrSCBars); for (int i = 0; i < arrSCBars.GetSize(); i++) if (arrSCBars[i] == this) { if (i > 0) m_dwSCBStyle |= IsHorzDocked() ? SCBS_EDGELEFT : SCBS_EDGETOP; if (i < arrSCBars.GetSize() - 1) m_dwSCBStyle |= IsHorzDocked() ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM; } } NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID); }
void CSizingControlBar::OnTrackUpdateSize(CPoint& point) { ASSERT(!IsFloating()); CPoint pt = point; ClientToScreen(&pt); CSize szDelta = pt - m_ptOld; 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); if (szDelta == CSize(0, 0)) return; // no size change 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++) if (!IsSideTracking()) { // track simultaneously CSizingControlBar* pBar = arrSCBars[i]; (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; CSizingControlBar* pBar = arrSCBars[i + ((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)]; (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= bHorz ? szDelta.cx : szDelta.cy; } OnTrackInvertTracker(); // redraw tracker at new pos if (m_bDragShowContent) m_pDockSite->DelayRecalcLayout(); }
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((int)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)); }
void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis) { arrSCBars.RemoveAll(); int nFirstT, nLastT, nThisT; GetRowInfo(nFirstT, nLastT, nThisT); nThis = -1; for (int i = nFirstT; i <= nLastT; i++) { CSizingControlBar* pBar = static_cast<CSizingControlBar*> (m_pDockBar->m_arrBars[i]); if (HIWORD(pBar) == 0) continue; // placeholder if (!pBar->IsVisible()) continue; if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar))) { if (pBar == this) nThis = arrSCBars.GetSize(); arrSCBars.Add(pBar); } } }
BOOL CSizingControlBar::NegociateSpace(int nLengthAvail, BOOL bHorz) { 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() - 2 : rcBar.Height() - 2); } CSCBArray arrSCBars; GetRowSizingBars(arrSCBars); CSizingControlBar* 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 - 2 : pBar->m_szVert.cy - 2; nMinLength += bHorz ? pBar->m_szMin.cx - 2: pBar->m_szMin.cy - 2; 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; if (nDelta == 0) break; } // clear m_bKeepSize flags if ((nDeltaOld == nDelta) || (nDelta == 0)) for (i = 0; i < arrSCBars.GetSize(); i++) arrSCBars[i]->m_bKeepSize = FALSE; } return TRUE; }
void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) { // compute the the client area CRect rcClient = lpncsp->rgrc[0]; rcClient.DeflateRect(5, 5); m_dwSCBStyle &= ~SCBS_EDGEALL; switch(m_nDockBarID) { case AFX_IDW_DOCKBAR_TOP: m_dwSCBStyle |= SCBS_EDGEBOTTOM; rcClient.DeflateRect(m_cyGripper, 0, 0, 0); break; case AFX_IDW_DOCKBAR_BOTTOM: m_dwSCBStyle |= SCBS_EDGETOP; rcClient.DeflateRect(m_cyGripper, 0, 0, 0); break; case AFX_IDW_DOCKBAR_LEFT: m_dwSCBStyle |= SCBS_EDGERIGHT; rcClient.DeflateRect(0, m_cyGripper, 0, 0); break; case AFX_IDW_DOCKBAR_RIGHT: m_dwSCBStyle |= SCBS_EDGELEFT; rcClient.DeflateRect(0, m_cyGripper, 0, 0); break; default: break; } if (!IsFloating() && m_pDockBar != NULL) { CSCBArray arrSCBars; GetRowSizingBars(arrSCBars); for (int i = 0; i < arrSCBars.GetSize(); i++) if (arrSCBars[i] == this) { if (i > 0) m_dwSCBStyle |= IsHorzDocked() ? SCBS_EDGELEFT : SCBS_EDGETOP; if (i < arrSCBars.GetSize() - 1) m_dwSCBStyle |= IsHorzDocked() ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM; } } // make room for edges only if they will be painted if (m_dwSCBStyle & SCBS_SHOWEDGES) rcClient.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); // "hide" button positioning CPoint ptOrgBtn; if (IsHorzDocked()) ptOrgBtn = CPoint(rcClient.left - m_cyGripper - 1, rcClient.top - 1); else ptOrgBtn = CPoint(rcClient.right - 11, rcClient.top - m_cyGripper - 1); m_biHide.Move(ptOrgBtn - CRect(lpncsp->rgrc[0]).TopLeft()); lpncsp->rgrc[0] = rcClient; }
BOOL CSizingControlBar::NegotiateSpace(int nLengthTotal, BOOL bHorz) { ASSERT(bHorz == IsHorzDocked()); int nFirst, nLast, nThis; GetRowInfo(nFirst, nLast, nThis); int nLengthAvail = nLengthTotal; int nLengthActual = 0; int nLengthMin = 2; int nWidthMax = 0; CSizingControlBar* pBar; for (int i = nFirst; i <= nLast; i++) { pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i]; if (HIWORD(pBar) == 0) continue; // placeholder if (!pBar->IsVisible()) continue; BOOL bIsSizingBar = pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)); 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 = (int)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 CSizingControlBar::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++) { CSizingControlBar* 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); CSizingControlBar* 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 : (int)arrSCBars.GetSize(); for (int i = nFirst; nDelta != 0 && i != nLimit; i += (bBefore ? -1 : 1)) { CSizingControlBar* 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 CSizingControlBar::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++) { CSizingControlBar* 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 }