sizecbar.cpp
上传用户:maryhy001
上传日期:2007-05-02
资源大小:2317k
文件大小:32k
- /////////////////////////////////////////////////////////////////////////
- // Copyright (C) 1998, 1999 by Cristi Posea
- // All rights reserved
- //
- // Use and distribute freely, except: don't remove my name from the
- // source or documentation (don't take credit for my work), mark your
- // changes (don't get me blamed for your possible bugs), don't alter
- // or remove this notice.
- // No warrantee of any kind, express or implied, is included with this
- // software; use at your own risk, responsibility for damages (if any) to
- // anyone resulting from the use of this software rests entirely with the
- // user.
- //
- // This class is intended to be used as a base class. Do not simply add
- // your code to this file - instead create a new class derived from
- // CSizingControlBar and put there what you need.
- // Modify this file only to fix bugs, and don't forget to send me a copy.
- //
- // Send bug reports, bug fixes, enhancements, requests, flames, etc.,
- // and I'll try to keep a version up to date. I can be reached at:
- // cristip@dundas.com
- //
- // More details at MFC Programmer's SourceBook
- // http://www.codeguru.com/docking/docking_window.shtml or search
- // www.codeguru.com for my name if the article was moved.
- //
- /////////////////////////////////////////////////////////////////////////
- //
- // Acknowledgements:
- // o Thanks to Harlan R. Seymour (harlans@dundas.com) for his continuous
- // support during development of this code.
- // o Thanks to Dundas Software for the opportunity to test this code
- // on real-life applications.
- // If you don't know who they are, visit them at www.dundas.com .
- // Their award winning components and development suites are
- // a pile of gold.
- // o Thanks to Chris Maunder (chrism@dundas.com) who came with the
- // simplest way to query "Show window content while dragging" system
- // setting.
- // o Thanks to Zafir Anjum (zafir@codeguru.com) for publishing this
- // code on his cool site (www.codeguru.com).
- // o Some ideas for the gripper came from the CToolBarEx flat toolbar
- // by Joerg Koenig (Joerg.Koenig@rhein-neckar.de). Also he inspired
- // me on writing this notice:) . Thanks, Joerg!
- // o Thanks to Jakawan Ratiwanich (jack@alpha.fsec.ucf.edu) and to
- // Udo Schaefer (Udo.Schaefer@vcase.de) for the dwStyle bug fix under
- // VC++ 6.0.
- // o And, of course, many thanks to all of you who used this code,
- // for the invaluable feedback I received.
- //
- /////////////////////////////////////////////////////////////////////////
- // sizecbar.cpp : implementation file
- //
- #include "stdafx.h"
- #include "sizecbar.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////
- // CSizingControlBar
- CSCBArray CSizingControlBar::m_arrBars; // static member
- IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
- CSizingControlBar::CSizingControlBar()
- {
- m_szMin = CSize(33, 32);
- m_szHorz = CSize(200, 200);
- m_szVert = CSize(200, 200);
- m_szFloat = CSize(200, 200);
- m_bTracking = FALSE;
- m_bKeepSize = FALSE;
- m_bParentSizing = FALSE;
- m_cxEdge = 5;
- m_bDragShowContent = FALSE;
- m_nDockBarID = 0;
- m_dwSCBStyle = 0;
- }
- CSizingControlBar::~CSizingControlBar()
- {
- }
- BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
- //{{AFX_MSG_MAP(CSizingControlBar)
- ON_WM_CREATE()
- ON_WM_PAINT()
- ON_WM_NCPAINT()
- ON_WM_NCCALCSIZE()
- ON_WM_WINDOWPOSCHANGING()
- ON_WM_CAPTURECHANGED()
- ON_WM_SETTINGCHANGE()
- ON_WM_LBUTTONUP()
- ON_WM_MOUSEMOVE()
- ON_WM_NCLBUTTONDOWN()
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONDBLCLK()
- ON_WM_RBUTTONDOWN()
- ON_WM_NCLBUTTONUP()
- ON_WM_NCMOUSEMOVE()
- ON_WM_NCHITTEST()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
- CSize sizeDefault, BOOL bHasGripper,
- UINT nID, DWORD dwStyle)
- {
- // must have a parent
- ASSERT_VALID(pParentWnd);
- // cannot be both fixed and dynamic
- // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
- ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
- (dwStyle & CBRS_SIZE_DYNAMIC)));
- m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
- m_szHorz = sizeDefault; // set the size members
- m_szVert = sizeDefault;
- m_szFloat = sizeDefault;
- m_cyGripper = bHasGripper ? 12 : 0; // set the gripper width
- // register and create the window - skip CControlBar::Create()
- CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
- ::LoadCursor(NULL, IDC_ARROW),
- ::GetSysColorBrush(COLOR_BTNFACE), 0);
- dwStyle &= ~CBRS_ALL; // keep only the generic window styles
- dwStyle |= WS_CLIPCHILDREN; // prevents flashing
- if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
- CRect(0, 0, 0, 0), pParentWnd, nID))
- return FALSE;
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////
- // CSizingControlBar message handlers
- int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (baseCSizingControlBar::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- // querry SPI_GETDRAGFULLWINDOWS system parameter
- // OnSettingChange() will update m_bDragShowContent
- m_bDragShowContent = FALSE;
- ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
- &m_bDragShowContent, 0);
- m_arrBars.Add(this); // register
-
- // m_dwSCBStyle |= SCBS_SHOWEDGES;
- return 0;
- }
- BOOL CSizingControlBar::DestroyWindow()
- {
- int nPos = FindSizingBar(this);
- ASSERT(nPos >= 0);
- m_arrBars.RemoveAt(nPos); // unregister
- return baseCSizingControlBar::DestroyWindow();
- }
- const BOOL CSizingControlBar::IsFloating() const
- {
- return !IsHorzDocked() && !IsVertDocked();
- }
- const BOOL CSizingControlBar::IsHorzDocked() const
- {
- return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
- m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
- }
- const BOOL CSizingControlBar::IsVertDocked() const
- {
- return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
- m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
- }
- const BOOL CSizingControlBar::IsSideTracking() const
- {
- // don't call this when not tracking
- ASSERT(m_bTracking && !IsFloating());
- return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
- IsHorzDocked() : IsVertDocked();
- }
- 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 - using CSCBDockBar to access 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(arrSCBars.GetSize());
- for (int i = 0; i < arrSCBars.GetSize(); i++)
- 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 nLengthAvail = bHorz ? rc.Width() + 2 : rc.Height() - 2;
- if (IsVisible() && !IsFloating() &&
- m_bParentSizing && arrSCBars[0] == this)
- if (NegociateSpace(nLengthAvail, (bHorz != FALSE)))
- AlignControlBars();
- m_bParentSizing = FALSE;
-
- CSize szRet = bHorz ? m_szHorz : m_szVert;
- szRet.cx = max(m_szMin.cx, szRet.cx);
- szRet.cy = max(m_szMin.cy, szRet.cy);
- return szRet;
- }
- CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
- {
- if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
- {
- if (nLength == -1)
- m_bParentSizing = TRUE;
- return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
- }
- if (dwMode & LM_MRUWIDTH) return m_szFloat;
- if (dwMode & LM_COMMIT) return m_szFloat; // already committed
- ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
- m_szFloat.cx = max(m_szFloat.cx, m_szMin.cx);
- m_szFloat.cy = max(m_szFloat.cy, m_szMin.cy);
- return m_szFloat;
- }
- void CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
- {
- // force non-client recalc if moved or resized
- lpwndpos->flags |= SWP_FRAMECHANGED;
- baseCSizingControlBar::OnWindowPosChanging(lpwndpos);
- // find on which side are we docked
- UINT nOldDockBarID = m_nDockBarID;
- m_nDockBarID = GetParent()->GetDlgCtrlID();
- if (!IsFloating())
- if (lpwndpos->flags & SWP_SHOWWINDOW)
- m_bKeepSize = TRUE;
- }
- /////////////////////////////////////////////////////////////////////////
- // Mouse Handling
- //
- void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
- {
- if (m_pDockBar != NULL)
- {
- // start the drag
- ASSERT(m_pDockContext != NULL);
- ClientToScreen(&point);
- m_pDockContext->StartDrag(point);
- }
- else
- CWnd::OnLButtonDown(nFlags, point);
- }
- void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
- {
- if (m_pDockBar != NULL)
- {
- // toggle docking
- ASSERT(m_pDockContext != NULL);
- m_pDockContext->ToggleDocking();
- }
- else
- CWnd::OnLButtonDblClk(nFlags, point);
- }
- void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
- {
- if (IsFloating())
- {
- baseCSizingControlBar::OnNcLButtonDown(nHitTest, point);
- return;
- }
- if (m_bTracking) return;
- if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
- StartTracking(nHitTest); // sizing edge hit
- }
- void CSizingControlBar::OnNcLButtonUp(UINT nHitTest, CPoint point)
- {
- if (nHitTest == HTCLOSE)
- m_pDockSite->ShowControlBar(this, FALSE, FALSE); // hide
- baseCSizingControlBar::OnNcLButtonUp(nHitTest, point);
- }
- void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
- {
- if (m_bTracking)
- StopTracking();
- baseCSizingControlBar::OnLButtonUp(nFlags, point);
- }
- void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
- {
- if (m_bTracking)
- StopTracking();
-
- baseCSizingControlBar::OnRButtonDown(nFlags, point);
- }
- 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)
- {
- // 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;
- }
- 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());
- // client area is not our bussiness :)
- dc.ExcludeClipRect(rcClient);
- // draw borders in non-client area
- CRect rcDraw = rcBar;
- DrawBorders(&dc, rcDraw);
- // erase parts not drawn
- dc.IntersectClipRect(rcDraw);
- // erase NC background the hard way
- HBRUSH hbr = (HBRUSH)GetClassLong(m_hWnd, GCL_HBRBACKGROUND);
- ::FillRect(dc.m_hDC, rcDraw, hbr);
- if (m_dwSCBStyle & SCBS_SHOWEDGES)
- {
- CRect rcEdge; // paint the sizing edges
- for (int i = 0; i < 4; i++)
- if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
- dc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
- ::GetSysColor(COLOR_BTNSHADOW));
- }
- if (m_cyGripper && !IsFloating())
- NcPaintGripper(&dc, rcClient);
- ReleaseDC(&dc);
- }
- void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
- {
- // paints a simple "two raised lines" gripper
- // override this if you want a more sophisticated gripper
- CRect gripper = rcClient;
- CRect rcbtn = m_biHide.GetRect();
- BOOL bHorz = IsHorzDocked();
-
- gripper.DeflateRect(1, 1);
- if (bHorz)
- { // gripper at left
- gripper.left -= m_cyGripper;
- gripper.right = gripper.left + 3;
- gripper.top = rcbtn.bottom + 3;
- }
- else
- { // gripper at top
- gripper.top -= m_cyGripper;
- gripper.bottom = gripper.top + 3;
- gripper.right = rcbtn.left - 3;
- }
- pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
- ::GetSysColor(COLOR_BTNSHADOW));
- gripper.OffsetRect(bHorz ? 3 : 0, bHorz ? 0 : 3);
-
- pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
- ::GetSysColor(COLOR_BTNSHADOW));
- m_biHide.Paint(pDC);
- }
- void CSizingControlBar::OnPaint()
- {
- // overridden to skip border painting based on clientrect
- CPaintDC dc(this);
- }
- UINT CSizingControlBar::OnNcHitTest(CPoint point)
- {
- if (IsFloating())
- return baseCSizingControlBar::OnNcHitTest(point);
- CRect rcBar, rcEdge;
- GetWindowRect(rcBar);
- 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 CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
- {
- baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
- m_bDragShowContent = FALSE;
- ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
- &m_bDragShowContent, 0); // update
- }
- /////////////////////////////////////////////////////////////////////////
- // CSizingControlBar implementation helpers
- void CSizingControlBar::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);
- 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 = 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_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
- 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 = m_szOld + (bHorz ? pBar->m_szHorz :
- pBar->m_szVert) - pBar->m_szMin;
- }
- 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;
- rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
- break;
- default:
- ASSERT(FALSE); // invalid hit test code
- }
- return TRUE;
- }
- UINT CSizingControlBar::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 no
- return HTNOWHERE;
- }
- void CSizingControlBar::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 CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
- {
- arrSCBars.RemoveAll();
- 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((CSizingControlBar*)pBar);
- }
- }
- const int CSizingControlBar::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 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::AlignControlBars()
- {
- int nFirst, nLast, nThis;
- GetRowInfo(nFirst, nLast, nThis);
- BOOL bHorz = IsHorzDocked();
- BOOL bNeedRecalc = FALSE;
- int nPos, nAlign = bHorz ? -2 : 0;
- CRect rc, rcDock;
- m_pDockBar->GetWindowRect(&rcDock);
- 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;
- pBar->GetWindowRect(&rc);
- rc.OffsetRect(-rcDock.TopLeft());
- if ((nPos = FindSizingBar(pBar)) >= 0)
- rc = CRect(rc.TopLeft(), bHorz ?
- m_arrBars[nPos]->m_szHorz : m_arrBars[nPos]->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();
- TRACE("cccn");
- }
- }
- void CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
- {
- 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);
- }
- void CSizingControlBar::LoadState(LPCTSTR lpszProfileName)
- {
- ASSERT_VALID(this);
- ASSERT(GetSafeHwnd()); // must be called after Create()
- CWinApp* pApp = AfxGetApp();
- TCHAR szSection[256];
- wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
- GetDlgCtrlID());
- m_szHorz.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
- _T("sizeHorzCX"), m_szHorz.cx));
- m_szHorz.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
- _T("sizeHorzCY"), m_szHorz.cy));
- m_szVert.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
- _T("sizeVertCX"), m_szVert.cx));
- m_szVert.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
- _T("sizeVertCY"), m_szVert.cy));
- m_szFloat.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
- _T("sizeFloatCX"), m_szFloat.cx));
- m_szFloat.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
- _T("sizeFloatCY"), m_szFloat.cy));
- }
- void CSizingControlBar::SaveState(LPCTSTR lpszProfileName)
- {
- // place your SaveState or GlobalSaveState call in
- // CMainFrame::DestroyWindow(), not in OnDestroy()
- ASSERT_VALID(this);
- ASSERT(GetSafeHwnd());
- CWinApp* pApp = AfxGetApp();
- TCHAR szSection[256];
- wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
- GetDlgCtrlID());
- pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx);
- pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy);
- pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx);
- pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy);
- pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx);
- pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy);
- }
- void CSizingControlBar::GlobalLoadState(LPCTSTR lpszProfileName)
- {
- for (int i = 0; i < m_arrBars.GetSize(); i++)
- ((CSizingControlBar*) m_arrBars[i])->LoadState(lpszProfileName);
- }
- void CSizingControlBar::GlobalSaveState(LPCTSTR lpszProfileName)
- {
- for (int i = 0; i < m_arrBars.GetSize(); i++)
- ((CSizingControlBar*) m_arrBars[i])->SaveState(lpszProfileName);
- }
- /////////////////////////////////////////////////////////////////////////
- // CSCBButton
- CSCBButton::CSCBButton()
- {
- bRaised = FALSE;
- bPushed = FALSE;
- }
- void CSCBButton::Paint(CDC* pDC)
- {
- CRect rc = GetRect();
- if (bPushed)
- pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNSHADOW),
- ::GetSysColor(COLOR_BTNHIGHLIGHT));
- else
- if (bRaised)
- pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNHIGHLIGHT),
- ::GetSysColor(COLOR_BTNSHADOW));
- COLORREF clrOldTextColor = pDC->GetTextColor();
- pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
- int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
- CFont font;
- int ppi = pDC->GetDeviceCaps(LOGPIXELSX);
- int pointsize = MulDiv(60, 96, ppi); // 6 points at 96 ppi
- font.CreatePointFont(pointsize, _T("Marlett"));
- CFont* oldfont = pDC->SelectObject(&font);
- pDC->TextOut(ptOrg.x + 2, ptOrg.y + 2, CString(_T("r"))); // x-like
-
- pDC->SelectObject(oldfont);
- pDC->SetBkMode(nPrevBkMode);
- pDC->SetTextColor(clrOldTextColor);
- }