📄 sizecbar.cpp
字号:
void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bTracking)
OnTrackUpdateSize(point);
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;
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::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);
}
*pRc = rc;
}
void CSizingControlBar::OnNcPaint()
{
// get window DC that is clipped to the non-client area
CWindowDC dc(this);
CRect rcClient, rcBar;
GetClientRect(rcClient);
ClientToScreen(rcClient);
GetWindowRect(rcBar);
rcClient.OffsetRect(-rcBar.TopLeft());
rcBar.OffsetRect(-rcBar.TopLeft());
CDC mdc;
mdc.CreateCompatibleDC(&dc);
CBitmap bm;
bm.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height());
CBitmap* pOldBm = mdc.SelectObject(&bm);
// client area is not our bussiness :)
dc.ExcludeClipRect(rcClient);
// draw borders in non-client area
CRect rcDraw = rcBar;
DrawBorders(&mdc, rcDraw);
// erase parts not drawn
mdc.IntersectClipRect(rcDraw);
// erase the NC background
mdc.FillRect(rcDraw, CBrush::FromHandle(
(HBRUSH) GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));
if (m_dwSCBStyle & SCBS_SHOWEDGES)
{
CRect rcEdge; // paint the sizing edges
for (int i = 0; i < 4; i++)
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
mdc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_BTNSHADOW));
}
NcPaintGripper(&mdc, rcClient);
dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &mdc, 0, 0, SRCCOPY);
ReleaseDC(&dc);
mdc.SelectObject(pOldBm);
bm.DeleteObject();
mdc.DeleteDC();
}
void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
{
UNUSED_ALWAYS(pDC);
UNUSED_ALWAYS(rcClient);
}
void CSizingControlBar::OnPaint()
{
// overridden to skip border painting based on clientrect
CPaintDC dc(this);
}
UINT CSizingControlBar::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);
return HTCLIENT;
}
void CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
m_bDragShowContent = FALSE;
::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
&m_bDragShowContent, 0); // update
}
void CSizingControlBar::OnSize(UINT nType, int cx, int cy)
{
UNUSED_ALWAYS(nType);
if ((m_dwSCBStyle & SCBS_SIZECHILD) != 0)
{
// automatic child resizing - only one child is allowed
CWnd* pWnd = GetWindow(GW_CHILD);
if (pWnd != NULL)
{
pWnd->MoveWindow(-1, -1, cx+1, cy+1);
ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL);
}
}
}
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)
{
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::StopTracking()
{
OnTrackInvertTracker(); // erase tracker
m_bTracking = FALSE;
ReleaseCapture();
m_pDockSite->DelayRecalcLayout();
}
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();
}
void CSizingControlBar::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);
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 CSizingControlBar::GetEdgeRect(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_cxEdge;
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
break;
case HTTOP:
if (!(m_dwSCBStyle & SCBS_EDGETOP)) return FALSE;
rcEdge.bottom = rcEdge.top + m_cxEdge;
rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
break;
case HTRIGHT:
if (!(m_dwSCBStyle & SCBS_EDGERIGHT)) return FALSE;
rcEdge.left = rcEdge.right - m_cxEdge;
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
break;
case HTBOTTOM:
if (!(m_dwSCBStyle & SCBS_EDGEBOTTOM)) return FALSE;
rcEdge.top = rcEdge.bottom - m_cxEdge;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -