sizecbar.cpp
上传用户:juying163
上传日期:2014-09-24
资源大小:5867k
文件大小:41k
源码类别:

GIS编程

开发平台:

Visual C++

  1. // sizecbar.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "sizecbar.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////
  11. // CSizingControlBar
  12. IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
  13. CSizingControlBar::CSizingControlBar()
  14. {
  15.     m_szMinHorz = CSize(33, 32);
  16.     m_szMinVert = CSize(33, 32);
  17.     m_szMinFloat = CSize(37, 32);
  18.     m_szHorz = CSize(200, 200);
  19.     m_szVert = CSize(200, 200);
  20.     m_szFloat = CSize(200, 200);
  21.     m_bTracking = FALSE;
  22.     m_bKeepSize = FALSE;
  23.     m_bParentSizing = FALSE;
  24.     m_cxEdge = 5;
  25.     m_bDragShowContent = FALSE;
  26.     m_nDockBarID = 0;
  27.     m_dwSCBStyle = 0;
  28. }
  29. CSizingControlBar::~CSizingControlBar()
  30. {
  31. }
  32. BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
  33.     //{{AFX_MSG_MAP(CSizingControlBar)
  34.     ON_WM_CREATE()
  35.     ON_WM_PAINT()
  36.     ON_WM_NCPAINT()
  37.     ON_WM_NCCALCSIZE()
  38.     ON_WM_WINDOWPOSCHANGING()
  39.     ON_WM_CAPTURECHANGED()
  40.     ON_WM_SETTINGCHANGE()
  41.     ON_WM_LBUTTONUP()
  42.     ON_WM_MOUSEMOVE()
  43.     ON_WM_NCLBUTTONDOWN()
  44.     ON_WM_LBUTTONDOWN()
  45.     ON_WM_LBUTTONDBLCLK()
  46.     ON_WM_RBUTTONDOWN()
  47.     ON_WM_NCMOUSEMOVE()
  48.     ON_WM_NCHITTEST()
  49.     ON_WM_CLOSE()
  50.     ON_WM_SIZE()
  51.     //}}AFX_MSG_MAP
  52.     ON_MESSAGE(WM_SETTEXT, OnSetText)
  53. END_MESSAGE_MAP()
  54. // old creation method, still here for compatibility reasons
  55. BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
  56.                                CSize sizeDefault, BOOL bHasGripper,
  57.                                UINT nID, DWORD dwStyle)
  58. {
  59.     UNUSED_ALWAYS(bHasGripper);
  60.     m_szHorz = m_szVert = m_szFloat = sizeDefault;
  61.     return Create(lpszWindowName, pParentWnd, nID, dwStyle);
  62. }
  63. // preffered creation method
  64. BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName,
  65.                                CWnd* pParentWnd, UINT nID,
  66.                                DWORD dwStyle)
  67. {
  68.     // must have a parent
  69.     ASSERT_VALID(pParentWnd);
  70.     // cannot be both fixed and dynamic
  71.     // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
  72.     ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
  73.               (dwStyle & CBRS_SIZE_DYNAMIC)));
  74.     m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
  75.     // register and create the window - skip CControlBar::Create()
  76.     CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
  77.         ::LoadCursor(NULL, IDC_ARROW),
  78.         ::GetSysColorBrush(COLOR_BTNFACE), 0);
  79.     dwStyle &= ~CBRS_ALL; // keep only the generic window styles
  80.     dwStyle |= WS_CLIPCHILDREN; // prevents flashing
  81.     if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
  82.         CRect(0, 0, 0, 0), pParentWnd, nID))
  83.         return FALSE;
  84.     return TRUE;
  85. }
  86. /////////////////////////////////////////////////////////////////////////
  87. // CSizingControlBar operations
  88. #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
  89. void CSizingControlBar::EnableDocking(DWORD dwDockStyle)
  90. {
  91.     // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  92.     ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
  93.     // cannot have the CBRS_FLOAT_MULTI style
  94.     ASSERT((dwDockStyle & CBRS_FLOAT_MULTI) == 0);
  95.     // the bar must have CBRS_SIZE_DYNAMIC style
  96.     ASSERT((m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
  97.     m_dwDockStyle = dwDockStyle;
  98.     if (m_pDockContext == NULL)
  99.         m_pDockContext = new CSCBDockContext(this);
  100.     // permanently wire the bar's owner to its current parent
  101.     if (m_hWndOwner == NULL)
  102.         m_hWndOwner = ::GetParent(m_hWnd);
  103. }
  104. #endif
  105. /////////////////////////////////////////////////////////////////////////
  106. // CSizingControlBar message handlers
  107. int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  108. {
  109.     if (baseCSizingControlBar::OnCreate(lpCreateStruct) == -1)
  110.         return -1;
  111.     // query SPI_GETDRAGFULLWINDOWS system parameter
  112.     // OnSettingChange() will update m_bDragShowContent
  113.     m_bDragShowContent = FALSE;
  114.     ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
  115.         &m_bDragShowContent, 0);
  116.     // uncomment this line if you want raised borders
  117. //    m_dwSCBStyle |= SCBS_SHOWEDGES;
  118.     return 0;
  119. }
  120. LRESULT CSizingControlBar::OnSetText(WPARAM wParam, LPARAM lParam)
  121. {
  122.     UNUSED_ALWAYS(wParam);
  123.     LRESULT lResult = CWnd::Default();
  124.     if (IsFloating() &&
  125.         GetParentFrame()->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
  126.     {
  127.         m_pDockBar->SetWindowText((LPCTSTR) lParam); // update dockbar
  128.         GetParentFrame()->DelayRecalcLayout(); // refresh miniframe
  129.     }
  130.     return lResult;
  131. }
  132. const BOOL CSizingControlBar::IsFloating() const
  133. {
  134.     return !IsHorzDocked() && !IsVertDocked();
  135. }
  136. const BOOL CSizingControlBar::IsHorzDocked() const
  137. {
  138.     return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  139.         m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  140. }
  141. const BOOL CSizingControlBar::IsVertDocked() const
  142. {
  143.     return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
  144.         m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
  145. }
  146. const BOOL CSizingControlBar::IsSideTracking() const
  147. {
  148.     // don't call this when not tracking
  149.     ASSERT(m_bTracking && !IsFloating());
  150.     return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
  151.         IsHorzDocked() : IsVertDocked();
  152. }
  153. CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  154. {
  155.     if (bStretch) // the bar is stretched (is not the child of a dockbar)
  156.         if (bHorz)
  157.             return CSize(32767, m_szHorz.cy);
  158.         else
  159.             return CSize(m_szVert.cx, 32767);
  160.     // dirty cast - we need access to protected CDockBar members
  161.     CSCBDockBar* pDockBar = (CSCBDockBar*) m_pDockBar;
  162.     // force imediate RecalcDelayShow() for all sizing bars on the row
  163.     // with delayShow/delayHide flags set to avoid IsVisible() problems
  164.     CSCBArray arrSCBars;
  165.     GetRowSizingBars(arrSCBars);
  166.     AFX_SIZEPARENTPARAMS layout;
  167.     layout.hDWP = pDockBar->m_bLayoutQuery ?
  168.         NULL : ::BeginDeferWindowPos(arrSCBars.GetSize());
  169.     for (int i = 0; i < arrSCBars.GetSize(); i++)
  170.         if (arrSCBars[i]->m_nStateFlags & (delayHide|delayShow))
  171.             arrSCBars[i]->RecalcDelayShow(&layout);
  172.     if (layout.hDWP != NULL)
  173.         ::EndDeferWindowPos(layout.hDWP);
  174.     // get available length
  175.     CRect rc = pDockBar->m_rectLayout;
  176.     if (rc.IsRectEmpty())
  177.         m_pDockSite->GetClientRect(&rc);
  178.     int nLengthTotal = bHorz ? rc.Width() + 2 : rc.Height() - 2;
  179.     if (IsVisible() && !IsFloating() &&
  180.         m_bParentSizing && arrSCBars[0] == this)
  181.         if (NegotiateSpace(nLengthTotal, (bHorz != FALSE)))
  182.             AlignControlBars();
  183.     m_bParentSizing = FALSE;
  184.     if (bHorz)
  185.         return CSize(max(m_szMinHorz.cx, m_szHorz.cx),
  186.                      max(m_szMinHorz.cy, m_szHorz.cy));
  187.     return CSize(max(m_szMinVert.cx, m_szVert.cx),
  188.                  max(m_szMinVert.cy, m_szVert.cy));
  189. }
  190. CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  191. {
  192.     if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
  193.     {
  194.         if (nLength == -1)
  195.             m_bParentSizing = TRUE;
  196.         return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
  197.     }
  198.     if (dwMode & LM_MRUWIDTH) return m_szFloat;
  199.     if (dwMode & LM_COMMIT) return m_szFloat; // already committed
  200. #ifndef _SCB_REPLACE_MINIFRAME
  201.     // check for dialgonal resizing hit test
  202.     int nHitTest = m_pDockContext->m_nHitTest;
  203.     if (IsFloating() &&
  204.         (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT ||
  205.         nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT))
  206.     {
  207.         CPoint ptCursor;
  208.         ::GetCursorPos(&ptCursor);
  209.         CRect rFrame, rBar;
  210.         GetParentFrame()->GetWindowRect(&rFrame);
  211.         GetWindowRect(&rBar);
  212.         
  213.         if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
  214.         {
  215.             m_szFloat.cx = rFrame.left + rBar.Width() - ptCursor.x;
  216.             m_pDockContext->m_rectFrameDragHorz.left = 
  217.                 min(ptCursor.x, rFrame.left + rBar.Width() - m_szMinFloat.cx);
  218.         }
  219.         if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
  220.         {
  221.             m_szFloat.cy = rFrame.top + rBar.Height() - ptCursor.y;
  222.             m_pDockContext->m_rectFrameDragHorz.top =
  223.                 min(ptCursor.y, rFrame.top + rBar.Height() - m_szMinFloat.cy);
  224.         }
  225.         if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
  226.             m_szFloat.cx = rBar.Width() + ptCursor.x - rFrame.right;
  227.         if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
  228.             m_szFloat.cy = rBar.Height() + ptCursor.y - rFrame.bottom;
  229.     }
  230.     else
  231. #endif //_SCB_REPLACE_MINIFRAME
  232.         ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
  233.     m_szFloat.cx = max(m_szFloat.cx, m_szMinFloat.cx);
  234.     m_szFloat.cy = max(m_szFloat.cy, m_szMinFloat.cy);
  235.     return m_szFloat;
  236. }
  237. void CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  238. {
  239.     // force non-client recalc if moved or resized
  240.     lpwndpos->flags |= SWP_FRAMECHANGED;
  241.     baseCSizingControlBar::OnWindowPosChanging(lpwndpos);
  242.     // find on which side are we docked
  243.     m_nDockBarID = GetParent()->GetDlgCtrlID();
  244.     if (!IsFloating())
  245.         if (lpwndpos->flags & SWP_SHOWWINDOW)
  246.             m_bKeepSize = TRUE;
  247. }
  248. /////////////////////////////////////////////////////////////////////////
  249. // Mouse Handling
  250. //
  251. void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
  252. {
  253.     if (m_pDockBar != NULL)
  254.     {
  255.         // start the drag
  256.         ASSERT(m_pDockContext != NULL);
  257.         ClientToScreen(&point);
  258.         m_pDockContext->StartDrag(point);
  259.     }
  260.     else
  261.         CWnd::OnLButtonDown(nFlags, point);
  262. }
  263. void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
  264. {
  265.     if (m_pDockBar != NULL)
  266.     {
  267.         // toggle docking
  268.         ASSERT(m_pDockContext != NULL);
  269.         m_pDockContext->ToggleDocking();
  270.     }
  271.     else
  272.         CWnd::OnLButtonDblClk(nFlags, point);
  273. }
  274. void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
  275. {
  276.     UNUSED_ALWAYS(point);
  277.     if (m_bTracking || IsFloating())
  278.         return;
  279.     if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
  280.         StartTracking(nHitTest, point); // sizing edge hit
  281. }
  282. void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
  283. {
  284.     if (m_bTracking)
  285.         StopTracking();
  286.     baseCSizingControlBar::OnLButtonUp(nFlags, point);
  287. }
  288. void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
  289. {
  290.     if (m_bTracking)
  291.         StopTracking();
  292.     baseCSizingControlBar::OnRButtonDown(nFlags, point);
  293. }
  294. void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
  295. {
  296.     if (m_bTracking)
  297.     {
  298.         CPoint ptScreen = point;
  299.         ClientToScreen(&ptScreen);
  300.         OnTrackUpdateSize(ptScreen);
  301.     }
  302.     baseCSizingControlBar::OnMouseMove(nFlags, point);
  303. }
  304. void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
  305. {
  306.     if (m_bTracking && (pWnd != this))
  307.         StopTracking();
  308.     baseCSizingControlBar::OnCaptureChanged(pWnd);
  309. }
  310. void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
  311.                                      NCCALCSIZE_PARAMS FAR* lpncsp)
  312. {
  313.     UNUSED_ALWAYS(bCalcValidRects);
  314. #ifndef _SCB_REPLACE_MINIFRAME
  315.     // Enable diagonal resizing for floating miniframe
  316.     if (IsFloating())
  317.     {
  318.         CFrameWnd* pFrame = GetParentFrame();
  319.         if (pFrame != NULL &&
  320.             pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
  321.         {
  322.             DWORD dwStyle = ::GetWindowLong(pFrame->m_hWnd, GWL_STYLE);
  323.             if ((dwStyle & MFS_4THICKFRAME) != 0)
  324.             {
  325.                 pFrame->ModifyStyle(MFS_4THICKFRAME, 0); // clear
  326.                 GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
  327.             }
  328.         }
  329.     }
  330. #endif _SCB_REPLACE_MINIFRAME
  331.     // compute the the client area
  332.     m_dwSCBStyle &= ~SCBS_EDGEALL;
  333.     // add resizing edges between bars on the same row
  334.     if (!IsFloating() && m_pDockBar != NULL)
  335.     {
  336.         CSCBArray arrSCBars;
  337.         int nThis;
  338.         GetRowSizingBars(arrSCBars, nThis);
  339.         BOOL bHorz = IsHorzDocked();
  340.         if (nThis > 0)
  341.             m_dwSCBStyle |= bHorz ? SCBS_EDGELEFT : SCBS_EDGETOP;
  342.         if (nThis < arrSCBars.GetUpperBound())
  343.             m_dwSCBStyle |= bHorz ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM;
  344.     }
  345.     NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID);
  346. }
  347. void CSizingControlBar::NcCalcClient(LPRECT pRc, UINT nDockBarID)
  348. {
  349.     CRect rc(pRc);
  350.     rc.DeflateRect(3, 5, 3, 3);
  351.     if (nDockBarID != AFX_IDW_DOCKBAR_FLOAT)
  352.         rc.DeflateRect(2, 0, 2, 2);
  353.     switch(nDockBarID)
  354.     {
  355.     case AFX_IDW_DOCKBAR_TOP:
  356.         m_dwSCBStyle |= SCBS_EDGEBOTTOM;
  357.         break;
  358.     case AFX_IDW_DOCKBAR_BOTTOM:
  359.         m_dwSCBStyle |= SCBS_EDGETOP;
  360.         break;
  361.     case AFX_IDW_DOCKBAR_LEFT:
  362.         m_dwSCBStyle |= SCBS_EDGERIGHT;
  363.         break;
  364.     case AFX_IDW_DOCKBAR_RIGHT:
  365.         m_dwSCBStyle |= SCBS_EDGELEFT;
  366.         break;
  367.     }
  368.     // make room for edges only if they will be painted
  369.     if (m_dwSCBStyle & SCBS_SHOWEDGES)
  370.         rc.DeflateRect(
  371.             (m_dwSCBStyle & SCBS_EDGELEFT) ? m_cxEdge : 0,
  372.             (m_dwSCBStyle & SCBS_EDGETOP) ? m_cxEdge : 0,
  373.             (m_dwSCBStyle & SCBS_EDGERIGHT) ? m_cxEdge : 0,
  374.             (m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_cxEdge : 0);
  375.     *pRc = rc;
  376. }
  377. void CSizingControlBar::OnNcPaint()
  378. {
  379.     // get window DC that is clipped to the non-client area
  380.     CWindowDC dc(this);
  381.     CRect rcClient, rcBar;
  382.     GetClientRect(rcClient);
  383.     ClientToScreen(rcClient);
  384.     GetWindowRect(rcBar);
  385.     rcClient.OffsetRect(-rcBar.TopLeft());
  386.     rcBar.OffsetRect(-rcBar.TopLeft());
  387.     CDC mdc;
  388.     mdc.CreateCompatibleDC(&dc);
  389.     
  390.     CBitmap bm;
  391.     bm.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height());
  392.     CBitmap* pOldBm = mdc.SelectObject(&bm);
  393.     // draw borders in non-client area
  394.     CRect rcDraw = rcBar;
  395.     DrawBorders(&mdc, rcDraw);
  396.     // erase the NC background
  397.     mdc.FillRect(rcDraw, CBrush::FromHandle(
  398.         (HBRUSH) GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));
  399.     if (m_dwSCBStyle & SCBS_SHOWEDGES)
  400.     {
  401.         CRect rcEdge; // paint the sizing edges
  402.         for (int i = 0; i < 4; i++)
  403.             if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
  404.                 mdc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  405.                     ::GetSysColor(COLOR_BTNSHADOW));
  406.     }
  407.     NcPaintGripper(&mdc, rcClient);
  408.     // client area is not our bussiness :)
  409.     dc.IntersectClipRect(rcBar);
  410.     dc.ExcludeClipRect(rcClient);
  411.     dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &mdc, 0, 0, SRCCOPY);
  412.     ReleaseDC(&dc);
  413.     mdc.SelectObject(pOldBm);
  414.     bm.DeleteObject();
  415.     mdc.DeleteDC();
  416. }
  417. void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
  418. {
  419.     UNUSED_ALWAYS(pDC);
  420.     UNUSED_ALWAYS(rcClient);
  421. }
  422. void CSizingControlBar::OnPaint()
  423. {
  424.     // overridden to skip border painting based on clientrect
  425.     CPaintDC dc(this);
  426. }
  427. UINT CSizingControlBar::OnNcHitTest(CPoint point)
  428. {
  429.     CRect rcBar, rcEdge;
  430.     GetWindowRect(rcBar);
  431.     if (!IsFloating())
  432.         for (int i = 0; i < 4; i++)
  433.             if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
  434.                 if (rcEdge.PtInRect(point))
  435.                     return GetEdgeHTCode(i);
  436.     return HTCLIENT;
  437. }
  438. void CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  439. {
  440.     baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
  441.     m_bDragShowContent = FALSE;
  442.     ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
  443.         &m_bDragShowContent, 0); // update
  444. }
  445. void CSizingControlBar::OnSize(UINT nType, int cx, int cy)
  446. {
  447.     UNUSED_ALWAYS(nType);
  448.     
  449.     if ((m_dwSCBStyle & SCBS_SIZECHILD) != 0)
  450.     {
  451.         // automatic child resizing - only one child is allowed
  452.         CWnd* pWnd = GetWindow(GW_CHILD);
  453.         if (pWnd != NULL)
  454.         {
  455.             pWnd->MoveWindow(0, 0, cx, cy);
  456.             ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL);
  457.         }
  458.     }
  459. }
  460. void CSizingControlBar::OnClose()
  461. {
  462.     // do nothing: protection against accidentally destruction by the
  463.     //   child control (i.e. if user hits Esc in a child editctrl)
  464. }
  465. /////////////////////////////////////////////////////////////////////////
  466. // CSizingControlBar implementation helpers
  467. void CSizingControlBar::StartTracking(UINT nHitTest, CPoint point)
  468. {
  469.     SetCapture();
  470.     // make sure no updates are pending
  471.     if (!m_bDragShowContent)
  472.         RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
  473.     m_htEdge = nHitTest;
  474.     m_bTracking = TRUE;
  475.     BOOL bHorz = IsHorzDocked();
  476.     BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  477.     m_nTrackPosOld = bHorzTracking ? point.x : point.y;
  478.     CRect rcBar, rcEdge;
  479.     GetWindowRect(rcBar);
  480.     GetEdgeRect(rcBar, m_htEdge, rcEdge);
  481.     m_nTrackEdgeOfs = m_nTrackPosOld -
  482.         (bHorzTracking ? rcEdge.CenterPoint().x : rcEdge.CenterPoint().y);
  483.     
  484.     CSCBArray arrSCBars;
  485.     int nThis;
  486.     GetRowSizingBars(arrSCBars, nThis);
  487.     m_nTrackPosMin = m_nTrackPosMax = m_nTrackPosOld;
  488.     if (!IsSideTracking())
  489.     {
  490.         // calc minwidth as the max minwidth of the sizing bars on row
  491.         int nMinWidth = bHorz ? m_szMinHorz.cy : m_szMinVert.cx;
  492.         for (int i = 0; i < arrSCBars.GetSize(); i++)
  493.             nMinWidth = max(nMinWidth, bHorz ? 
  494.                 arrSCBars[i]->m_szMinHorz.cy :
  495.                 arrSCBars[i]->m_szMinVert.cx);
  496.         int nExcessWidth = (bHorz ? m_szHorz.cy : m_szVert.cx) - nMinWidth;
  497.         // the control bar cannot grow with more than the width of
  498.         // remaining client area of the mainframe
  499.         CRect rcT;
  500.         m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
  501.             reposQuery, &rcT, NULL, TRUE);
  502.         int nMaxWidth = bHorz ? rcT.Height() - 2 : rcT.Width() - 2;
  503.         BOOL bTopOrLeft = m_htEdge == HTTOP || m_htEdge == HTLEFT;
  504.         m_nTrackPosMin -= bTopOrLeft ? nMaxWidth : nExcessWidth;
  505.         m_nTrackPosMax += bTopOrLeft ? nExcessWidth : nMaxWidth;
  506.     }
  507.     else
  508.     {
  509.         // side tracking:
  510.         // max size is the actual size plus the amount the other
  511.         // sizing bars can be decreased until they reach their minsize
  512.         if (m_htEdge == HTBOTTOM || m_htEdge == HTRIGHT)
  513.             nThis++;
  514.         for (int i = 0; i < arrSCBars.GetSize(); i++)
  515.         {
  516.             CSizingControlBar* pBar = arrSCBars[i];
  517.             int nExcessWidth = bHorz ? 
  518.                 pBar->m_szHorz.cx - pBar->m_szMinHorz.cx :
  519.                 pBar->m_szVert.cy - pBar->m_szMinVert.cy;
  520.             if (i < nThis)
  521.                 m_nTrackPosMin -= nExcessWidth;
  522.             else
  523.                 m_nTrackPosMax += nExcessWidth;
  524.         }
  525.     }
  526.     OnTrackInvertTracker(); // draw tracker
  527. }
  528. void CSizingControlBar::StopTracking()
  529. {
  530.     OnTrackInvertTracker(); // erase tracker
  531.     m_bTracking = FALSE;
  532.     ReleaseCapture();
  533.     m_pDockSite->DelayRecalcLayout();
  534. }
  535. void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
  536. {
  537.     ASSERT(!IsFloating());
  538.     BOOL bHorzTrack = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  539.     int nTrackPos = bHorzTrack ? point.x : point.y;
  540.     nTrackPos = max(m_nTrackPosMin, min(m_nTrackPosMax, nTrackPos));
  541.     int nDelta = nTrackPos - m_nTrackPosOld;
  542.     if (nDelta == 0)
  543.         return; // no pos change
  544.     OnTrackInvertTracker(); // erase tracker
  545.     m_nTrackPosOld = nTrackPos;
  546.     
  547.     BOOL bHorz = IsHorzDocked();
  548.     CSize sizeNew = bHorz ? m_szHorz : m_szVert;
  549.     switch (m_htEdge)
  550.     {
  551.     case HTLEFT:    sizeNew -= CSize(nDelta, 0); break;
  552.     case HTTOP:     sizeNew -= CSize(0, nDelta); break;
  553.     case HTRIGHT:   sizeNew += CSize(nDelta, 0); break;
  554.     case HTBOTTOM:  sizeNew += CSize(0, nDelta); break;
  555.     }
  556.     CSCBArray arrSCBars;
  557.     int nThis;
  558.     GetRowSizingBars(arrSCBars, nThis);
  559.     if (!IsSideTracking())
  560.         for (int i = 0; i < arrSCBars.GetSize(); i++)
  561.         {
  562.             CSizingControlBar* pBar = arrSCBars[i];
  563.             // make same width (or height)
  564.             (bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
  565.                 bHorz ? sizeNew.cy : sizeNew.cx;
  566.         }
  567.     else
  568.     {
  569.         int nGrowingBar = nThis;
  570.         BOOL bBefore = m_htEdge == HTTOP || m_htEdge == HTLEFT;
  571.         if (bBefore && nDelta > 0)
  572.             nGrowingBar--;
  573.         if (!bBefore && nDelta < 0)
  574.             nGrowingBar++;
  575.         if (nGrowingBar != nThis)
  576.             bBefore = !bBefore;
  577.         // nGrowing is growing
  578.         nDelta = abs(nDelta);
  579.         CSizingControlBar* pBar = arrSCBars[nGrowingBar];
  580.         (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta;
  581.         // the others are shrinking
  582.         int nFirst = bBefore ? nGrowingBar - 1 : nGrowingBar + 1;
  583.         int nLimit = bBefore ? -1 : arrSCBars.GetSize();
  584.         for (int i = nFirst; nDelta != 0 && i != nLimit; i += (bBefore ? -1 : 1))
  585.         {
  586.             CSizingControlBar* pBar = arrSCBars[i];
  587.                 
  588.             int nDeltaT = min(nDelta,
  589.                 (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -
  590.                 (bHorz ? pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy));
  591.             (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= nDeltaT;
  592.             nDelta -= nDeltaT;
  593.         }
  594.     }
  595.     OnTrackInvertTracker(); // redraw tracker at new pos
  596.     if (m_bDragShowContent)
  597.         m_pDockSite->DelayRecalcLayout();
  598. }
  599. void CSizingControlBar::OnTrackInvertTracker()
  600. {
  601.     ASSERT(m_bTracking);
  602.     if (m_bDragShowContent)
  603.         return; // don't show tracker if DragFullWindows is on
  604.     BOOL bHorz = IsHorzDocked();
  605.     CRect rc, rcBar, rcDock, rcFrame;
  606.     GetWindowRect(rcBar);
  607.     m_pDockBar->GetWindowRect(rcDock);
  608.     m_pDockSite->GetWindowRect(rcFrame);
  609.     VERIFY(GetEdgeRect(rcBar, m_htEdge, rc));
  610.     if (!IsSideTracking())
  611.         rc = bHorz ? 
  612.             CRect(rcDock.left + 1, rc.top, rcDock.right - 1, rc.bottom) :
  613.             CRect(rc.left, rcDock.top + 1, rc.right, rcDock.bottom - 1);
  614.     BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  615.     int nOfs = m_nTrackPosOld - m_nTrackEdgeOfs;
  616.     nOfs -= bHorzTracking ? rc.CenterPoint().x : rc.CenterPoint().y;
  617.     rc.OffsetRect(bHorzTracking ? nOfs : 0, bHorzTracking ? 0 : nOfs);
  618.     rc.OffsetRect(-rcFrame.TopLeft());
  619.     CDC *pDC = m_pDockSite->GetDCEx(NULL,
  620.         DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
  621.     CBrush* pBrush = CDC::GetHalftoneBrush();
  622.     CBrush* pBrushOld = pDC->SelectObject(pBrush);
  623.     pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
  624.     
  625.     pDC->SelectObject(pBrushOld);
  626.     m_pDockSite->ReleaseDC(pDC);
  627. }
  628. BOOL CSizingControlBar::GetEdgeRect(CRect rcWnd, UINT nHitTest,
  629.                                     CRect& rcEdge)
  630. {
  631.     rcEdge = rcWnd;
  632.     if (m_dwSCBStyle & SCBS_SHOWEDGES)
  633.         rcEdge.DeflateRect(1, 1);
  634.     BOOL bHorz = IsHorzDocked();
  635.     switch (nHitTest)
  636.     {
  637.     case HTLEFT:
  638.         if (!(m_dwSCBStyle & SCBS_EDGELEFT)) return FALSE;
  639.         rcEdge.right = rcEdge.left + m_cxEdge;
  640.         rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
  641.         break;
  642.     case HTTOP:
  643.         if (!(m_dwSCBStyle & SCBS_EDGETOP)) return FALSE;
  644.         rcEdge.bottom = rcEdge.top + m_cxEdge;
  645.         rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
  646.         break;
  647.     case HTRIGHT:
  648.         if (!(m_dwSCBStyle & SCBS_EDGERIGHT)) return FALSE;
  649.         rcEdge.left = rcEdge.right - m_cxEdge;
  650.         rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
  651.         break;
  652.     case HTBOTTOM:
  653.         if (!(m_dwSCBStyle & SCBS_EDGEBOTTOM)) return FALSE;
  654.         rcEdge.top = rcEdge.bottom - m_cxEdge;
  655.         rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
  656.         break;
  657.     default:
  658.         ASSERT(FALSE); // invalid hit test code
  659.     }
  660.     return TRUE;
  661. }
  662. UINT CSizingControlBar::GetEdgeHTCode(int nEdge)
  663. {
  664.     if (nEdge == 0) return HTLEFT;
  665.     if (nEdge == 1) return HTTOP;
  666.     if (nEdge == 2) return HTRIGHT;
  667.     if (nEdge == 3) return HTBOTTOM;
  668.     ASSERT(FALSE); // invalid edge code
  669.     return HTNOWHERE;
  670. }
  671. void CSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
  672. {
  673.     ASSERT_VALID(m_pDockBar); // verify bounds
  674.     nThis = m_pDockBar->FindBar(this);
  675.     ASSERT(nThis != -1);
  676.     int i, nBars = m_pDockBar->m_arrBars.GetSize();
  677.     // find the first and the last bar in row
  678.     for (nFirst = -1, i = nThis - 1; i >= 0 && nFirst == -1; i--)
  679.         if (m_pDockBar->m_arrBars[i] == NULL)
  680.             nFirst = i + 1;
  681.     for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
  682.         if (m_pDockBar->m_arrBars[i] == NULL)
  683.             nLast = i - 1;
  684.     ASSERT((nLast != -1) && (nFirst != -1));
  685. }
  686. void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
  687. {
  688.     int nThis; // dummy
  689.     GetRowSizingBars(arrSCBars, nThis);
  690. }
  691. void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
  692. {
  693.     arrSCBars.RemoveAll();
  694.     int nFirstT, nLastT, nThisT;
  695.     GetRowInfo(nFirstT, nLastT, nThisT);
  696.     nThis = -1;
  697.     for (int i = nFirstT; i <= nLastT; i++)
  698.     {
  699.         CSizingControlBar* pBar =
  700.             (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  701.         if (HIWORD(pBar) == 0) continue; // placeholder
  702.         if (!pBar->IsVisible()) continue;
  703.         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  704.         {
  705.             if (pBar == this)
  706.                 nThis = arrSCBars.GetSize();
  707.             arrSCBars.Add(pBar);
  708.         }
  709.     }
  710. }
  711. BOOL CSizingControlBar::NegotiateSpace(int nLengthTotal, BOOL bHorz)
  712. {
  713.     ASSERT(bHorz == IsHorzDocked());
  714.     int nFirst, nLast, nThis;
  715.     GetRowInfo(nFirst, nLast, nThis);
  716.     int nLengthAvail = nLengthTotal;
  717.     int nLengthActual = 0;
  718.     int nLengthMin = 2;
  719.     int nWidthMax = 0;
  720.     CSizingControlBar* pBar;
  721.     for (int i = nFirst; i <= nLast; i++)
  722.     {
  723.         pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  724.         if (HIWORD(pBar) == 0) continue; // placeholder
  725.         if (!pBar->IsVisible()) continue;
  726.         BOOL bIsSizingBar = 
  727.             pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar));
  728.         int nLengthBar; // minimum length of the bar
  729.         if (bIsSizingBar)
  730.             nLengthBar = bHorz ? pBar->m_szMinHorz.cx - 2 :
  731.                 pBar->m_szMinVert.cy - 2;
  732.         else
  733.         {
  734.             CRect rcBar;
  735.             pBar->GetWindowRect(&rcBar);
  736.             nLengthBar = bHorz ? rcBar.Width() - 2 : rcBar.Height() - 2;
  737.         }
  738.         nLengthMin += nLengthBar;
  739.         if (nLengthMin > nLengthTotal)
  740.         {
  741.             // split the row after fixed bar
  742.             if (i < nThis)
  743.             {
  744.                 m_pDockBar->m_arrBars.InsertAt(i + 1,
  745.                     (CControlBar*) NULL);
  746.                 return FALSE;
  747.             }
  748.             
  749.             // only this sizebar remains on the row, adjust it to minsize
  750.             if (i == nThis)
  751.             {
  752.                 if (bHorz)
  753.                     m_szHorz.cx = m_szMinHorz.cx;
  754.                 else
  755.                     m_szVert.cy = m_szMinVert.cy;
  756.                 return TRUE; // the dockbar will split the row for us
  757.             }
  758.             // we have enough bars - go negotiate with them
  759.             m_pDockBar->m_arrBars.InsertAt(i, (CControlBar*) NULL);
  760.             nLast = i - 1;
  761.             break;
  762.         }
  763.         if (bIsSizingBar)
  764.         {
  765.             nLengthActual += bHorz ? pBar->m_szHorz.cx - 2 : 
  766.                 pBar->m_szVert.cy - 2;
  767.             nWidthMax = max(nWidthMax, bHorz ? pBar->m_szHorz.cy :
  768.                 pBar->m_szVert.cx);
  769.         }
  770.         else
  771.             nLengthAvail -= nLengthBar;
  772.     }
  773.     CSCBArray arrSCBars;
  774.     GetRowSizingBars(arrSCBars);
  775.     int nNumBars = arrSCBars.GetSize();
  776.     int nDelta = nLengthAvail - nLengthActual;
  777.     // return faster when there is only one sizing bar per row (this one)
  778.     if (nNumBars == 1)
  779.     {
  780.         ASSERT(arrSCBars[0] == this);
  781.         if (nDelta == 0)
  782.             return TRUE;
  783.         
  784.         m_bKeepSize = FALSE;
  785.         (bHorz ? m_szHorz.cx : m_szVert.cy) += nDelta;
  786.         return TRUE;
  787.     }
  788.     // make all the bars the same width
  789.     for (i = 0; i < nNumBars; i++)
  790.         if (bHorz)
  791.             arrSCBars[i]->m_szHorz.cy = nWidthMax;
  792.         else
  793.             arrSCBars[i]->m_szVert.cx = nWidthMax;
  794.     // distribute the difference between the bars,
  795.     // but don't shrink them below their minsizes
  796.     while (nDelta != 0)
  797.     {
  798.         int nDeltaOld = nDelta;
  799.         for (i = 0; i < nNumBars; i++)
  800.         {
  801.             pBar = arrSCBars[i];
  802.             int nLMin = bHorz ?
  803.                 pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy;
  804.             int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;
  805.             if ((nL == nLMin) && (nDelta < 0) || // already at min length
  806.                 pBar->m_bKeepSize) // or wants to keep its size
  807.                 continue;
  808.             // sign of nDelta
  809.             int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
  810.             (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta2;
  811.             nDelta -= nDelta2;
  812.             if (nDelta == 0) break;
  813.         }
  814.         // clear m_bKeepSize flags
  815.         if ((nDeltaOld == nDelta) || (nDelta == 0))
  816.             for (i = 0; i < nNumBars; i++)
  817.                 arrSCBars[i]->m_bKeepSize = FALSE;
  818.     }
  819.     return TRUE;
  820. }
  821. void CSizingControlBar::AlignControlBars()
  822. {
  823.     int nFirst, nLast, nThis;
  824.     GetRowInfo(nFirst, nLast, nThis);
  825.     BOOL bHorz = IsHorzDocked();
  826.     BOOL bNeedRecalc = FALSE;
  827.     int nAlign = bHorz ? -2 : 0;
  828.     CRect rc, rcDock;
  829.     m_pDockBar->GetWindowRect(&rcDock);
  830.     for (int i = nFirst; i <= nLast; i++)
  831.     {
  832.         CSizingControlBar* pBar =
  833.             (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  834.         if (HIWORD(pBar) == 0) continue; // placeholder
  835.         if (!pBar->IsVisible()) continue;
  836.         pBar->GetWindowRect(&rc);
  837.         rc.OffsetRect(-rcDock.TopLeft());
  838.         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  839.             rc = CRect(rc.TopLeft(),
  840.                 bHorz ? pBar->m_szHorz : pBar->m_szVert);
  841.         if ((bHorz ? rc.left : rc.top) != nAlign)
  842.         {
  843.             if (!bHorz)
  844.                 rc.OffsetRect(0, nAlign - rc.top - 2);
  845.             else if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
  846.                 rc.OffsetRect(nAlign - rc.left, -2);
  847.             else
  848.                 rc.OffsetRect(nAlign - rc.left, 0);
  849.             pBar->MoveWindow(rc);
  850.             bNeedRecalc = TRUE;
  851.         }
  852.         nAlign += (bHorz ? rc.Width() : rc.Height()) - 2;
  853.     }
  854.     if (bNeedRecalc)
  855.         m_pDockSite->DelayRecalcLayout();
  856. }
  857. void CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget,
  858.                                       BOOL bDisableIfNoHndler)
  859. {
  860.     UNUSED_ALWAYS(bDisableIfNoHndler);
  861.     UNUSED_ALWAYS(pTarget);
  862. }
  863. void CSizingControlBar::LoadState(LPCTSTR lpszProfileName)
  864. {
  865.     ASSERT_VALID(this);
  866.     ASSERT(GetSafeHwnd()); // must be called after Create()
  867. #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
  868.     // compensate the caption miscalculation in CFrameWnd::SetDockState()
  869.     CDockState state;
  870.     state.LoadState(lpszProfileName);
  871.     UINT nID = GetDlgCtrlID();
  872.     for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++)
  873.     {
  874.         CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
  875.         ASSERT(pInfo != NULL);
  876.         if (!pInfo->m_bFloating)
  877.             continue;
  878.         
  879.         // this is a floating dockbar - check the ID array
  880.         for (int j = 0; j < pInfo->m_arrBarID.GetSize(); j++)
  881.             if ((DWORD) pInfo->m_arrBarID[j] == nID)
  882.             {
  883.                 // found this bar - offset origin and save settings
  884.                 pInfo->m_pointPos.x++;
  885.                 pInfo->m_pointPos.y +=
  886.                     ::GetSystemMetrics(SM_CYSMCAPTION) + 1;
  887.                 pInfo->SaveState(lpszProfileName, i);
  888.             }
  889.     }
  890. #endif //_SCB_REPLACE_MINIFRAME && !_SCB_MINIFRAME_CAPTION
  891.     CWinApp* pApp = AfxGetApp();
  892.     TCHAR szSection[256];
  893.     wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
  894.         GetDlgCtrlID());
  895.     m_szHorz.cx = max(m_szMinHorz.cx, (int) pApp->GetProfileInt(
  896.         szSection, _T("sizeHorzCX"), m_szHorz.cx));
  897.     m_szHorz.cy = max(m_szMinHorz.cy, (int) pApp->GetProfileInt(
  898.         szSection, _T("sizeHorzCY"), m_szHorz.cy));
  899.     m_szVert.cx = max(m_szMinVert.cx, (int) pApp->GetProfileInt(
  900.         szSection, _T("sizeVertCX"), m_szVert.cx));
  901.     m_szVert.cy = max(m_szMinVert.cy, (int) pApp->GetProfileInt(
  902.         szSection, _T("sizeVertCY"), m_szVert.cy));
  903.     m_szFloat.cx = max(m_szMinFloat.cx, (int) pApp->GetProfileInt(
  904.         szSection, _T("sizeFloatCX"), m_szFloat.cx));
  905.     m_szFloat.cy = max(m_szMinFloat.cy, (int) pApp->GetProfileInt(
  906.         szSection, _T("sizeFloatCY"), m_szFloat.cy));
  907. }
  908. void CSizingControlBar::SaveState(LPCTSTR lpszProfileName)
  909. {
  910.     // place your SaveState or GlobalSaveState call in
  911.     // CMainFrame's OnClose() or DestroyWindow(), not in OnDestroy()
  912.     ASSERT_VALID(this);
  913.     ASSERT(GetSafeHwnd());
  914.     CWinApp* pApp = AfxGetApp();
  915.     TCHAR szSection[256];
  916.     wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
  917.         GetDlgCtrlID());
  918.     pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx);
  919.     pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy);
  920.     pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx);
  921.     pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy);
  922.     pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx);
  923.     pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy);
  924. }
  925. void CSizingControlBar::GlobalLoadState(CFrameWnd* pFrame,
  926.                                         LPCTSTR lpszProfileName)
  927. {
  928.     POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
  929.     while (pos != NULL)
  930.     {
  931.         CSizingControlBar* pBar = 
  932.             (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
  933.         ASSERT(pBar != NULL);
  934.         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  935.             pBar->LoadState(lpszProfileName);
  936.     }
  937. }
  938. void CSizingControlBar::GlobalSaveState(CFrameWnd* pFrame,
  939.                                         LPCTSTR lpszProfileName)
  940. {
  941.     POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
  942.     while (pos != NULL)
  943.     {
  944.         CSizingControlBar* pBar =
  945.             (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
  946.         ASSERT(pBar != NULL);
  947.         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  948.             pBar->SaveState(lpszProfileName);
  949.     }
  950. }
  951. #ifdef _SCB_REPLACE_MINIFRAME
  952. #ifndef _SCB_MINIFRAME_CAPTION
  953. /////////////////////////////////////////////////////////////////////////////
  954. // CSCBDockContext Drag Operations
  955. static void AdjustRectangle(CRect& rect, CPoint pt)
  956. {
  957.     int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  958.                     (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  959.     int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  960.                     (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  961.     rect.OffsetRect(nXOffset, nYOffset);
  962. }
  963. void CSCBDockContext::StartDrag(CPoint pt)
  964. {
  965.     ASSERT_VALID(m_pBar);
  966.     m_bDragging = TRUE;
  967.     InitLoop();
  968.     ASSERT((m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
  969.     // get true bar size (including borders)
  970.     CRect rect;
  971.     m_pBar->GetWindowRect(rect);
  972.     m_ptLast = pt;
  973.     CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
  974.     CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
  975.     CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  976.     m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  977.     m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  978.     // calculate frame dragging rectangle
  979.     m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
  980. #ifdef _MAC
  981.     CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
  982.         WS_THICKFRAME, WS_EX_FORCESIZEBOX);
  983. #else
  984.     CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz, WS_THICKFRAME);
  985. #endif
  986.     m_rectFrameDragHorz.DeflateRect(2, 2);
  987.     m_rectFrameDragVert = m_rectFrameDragHorz;
  988.     
  989.     // adjust rectangles so that point is inside
  990.     AdjustRectangle(m_rectDragHorz, pt);
  991.     AdjustRectangle(m_rectDragVert, pt);
  992.     AdjustRectangle(m_rectFrameDragHorz, pt);
  993.     AdjustRectangle(m_rectFrameDragVert, pt);
  994.     // initialize tracking state and enter tracking loop
  995.     m_dwOverDockStyle = CanDock();
  996.     Move(pt);   // call it here to handle special keys
  997.     Track();
  998. }
  999. #endif //_SCB_MINIFRAME_CAPTION
  1000. /////////////////////////////////////////////////////////////////////////////
  1001. // CSCBMiniDockFrameWnd
  1002. IMPLEMENT_DYNCREATE(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd);
  1003. BEGIN_MESSAGE_MAP(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd)
  1004.     //{{AFX_MSG_MAP(CSCBMiniDockFrameWnd)
  1005.     ON_WM_NCLBUTTONDOWN()
  1006.     ON_WM_GETMINMAXINFO()
  1007.     ON_WM_WINDOWPOSCHANGING()
  1008.     ON_WM_SIZE()
  1009.     //}}AFX_MSG_MAP
  1010. END_MESSAGE_MAP()
  1011. BOOL CSCBMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
  1012. {
  1013.     // set m_bInRecalcLayout to avoid flashing during creation
  1014.     // RecalcLayout will be called once something is docked
  1015.     m_bInRecalcLayout = TRUE;
  1016.     DWORD dwStyle = WS_POPUP|WS_CAPTION|WS_SYSMENU|MFS_MOVEFRAME|
  1017.         MFS_4THICKFRAME|MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|
  1018.         FWS_SNAPTOBARS;
  1019.     if (dwBarStyle & CBRS_SIZE_DYNAMIC)
  1020.         dwStyle &= ~MFS_MOVEFRAME;
  1021.     DWORD dwExStyle = 0;
  1022. #ifdef _MAC
  1023.     if (dwBarStyle & CBRS_SIZE_DYNAMIC)
  1024.         dwExStyle |= WS_EX_FORCESIZEBOX;
  1025.     else
  1026.         dwStyle &= ~(MFS_MOVEFRAME|MFS_4THICKFRAME);
  1027. #endif
  1028.     if (!CMiniFrameWnd::CreateEx(dwExStyle,
  1029.         NULL, &afxChNil, dwStyle, rectDefault, pParent))
  1030.     {
  1031.         m_bInRecalcLayout = FALSE;
  1032.         return FALSE;
  1033.     }
  1034.     dwStyle = dwBarStyle & (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ?
  1035.         CBRS_ALIGN_LEFT : CBRS_ALIGN_TOP;
  1036.     dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI;
  1037.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  1038.     //pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);
  1039.     CString strHide;
  1040.     if (strHide.LoadString(AFX_IDS_HIDE))
  1041.     {
  1042.         pSysMenu->DeleteMenu(SC_CLOSE, MF_BYCOMMAND);
  1043.         pSysMenu->AppendMenu(MF_STRING|MF_ENABLED, SC_CLOSE, strHide);
  1044.     }
  1045.     // must initially create with parent frame as parent
  1046.     if (!m_wndDockBar.Create(pParent, WS_CHILD | WS_VISIBLE | dwStyle,
  1047.         AFX_IDW_DOCKBAR_FLOAT))
  1048.     {
  1049.         m_bInRecalcLayout = FALSE;
  1050.         return FALSE;
  1051.     }
  1052.     // set parent to CMiniDockFrameWnd
  1053.     m_wndDockBar.SetParent(this);
  1054.     m_bInRecalcLayout = FALSE;
  1055.     return TRUE;
  1056. }
  1057. void CSCBMiniDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
  1058. {
  1059.     if (nHitTest == HTCAPTION || nHitTest == HTCLOSE)
  1060.     {
  1061.         baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
  1062.         return;
  1063.     }
  1064.     if (GetSizingControlBar() != NULL)
  1065.         CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
  1066.     else
  1067.         baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
  1068. }
  1069. CSizingControlBar* CSCBMiniDockFrameWnd::GetSizingControlBar()
  1070. {
  1071.     CWnd* pWnd = GetWindow(GW_CHILD); // get the dockbar
  1072.     if (pWnd == NULL)
  1073.         return NULL;
  1074.     
  1075.     pWnd = pWnd->GetWindow(GW_CHILD); // get the controlbar
  1076.     if (pWnd == NULL)
  1077.         return NULL;
  1078.     if (!pWnd->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  1079.         return NULL;
  1080.     return (CSizingControlBar*) pWnd;
  1081. }
  1082. void CSCBMiniDockFrameWnd::OnSize(UINT nType, int cx, int cy) 
  1083. {
  1084.     CSizingControlBar* pBar = GetSizingControlBar();
  1085.     if ((pBar != NULL) && (GetStyle() & MFS_4THICKFRAME) == 0
  1086.         && pBar->IsVisible())
  1087.         pBar->m_szFloat = CSize(cx + 4, cy + 4);
  1088.     baseCSCBMiniDockFrameWnd::OnSize(nType, cx, cy);
  1089. }
  1090. void CSCBMiniDockFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
  1091. {
  1092.     baseCSCBMiniDockFrameWnd::OnGetMinMaxInfo(lpMMI);
  1093.     CSizingControlBar* pBar = GetSizingControlBar();
  1094.     if (pBar != NULL)
  1095.     {
  1096.         CRect r(CPoint(0, 0), pBar->m_szMinFloat - CSize(4, 4));
  1097. #ifndef _SCB_MINIFRAME_CAPTION
  1098.         CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME);
  1099. #else
  1100.         CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME|WS_CAPTION);
  1101. #endif //_SCB_MINIFRAME_CAPTION
  1102.         lpMMI->ptMinTrackSize.x = r.Width();
  1103.         lpMMI->ptMinTrackSize.y = r.Height();
  1104.     }
  1105. }
  1106. void CSCBMiniDockFrameWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
  1107. {
  1108.     if ((GetStyle() & MFS_4THICKFRAME) != 0)
  1109.     {
  1110.         CSizingControlBar* pBar = GetSizingControlBar();
  1111.         if (pBar != NULL)
  1112.         {
  1113.             lpwndpos->flags |= SWP_NOSIZE; // don't size this time
  1114.             // prevents flicker
  1115.             pBar->m_pDockBar->ModifyStyle(0, WS_CLIPCHILDREN);
  1116.             // enable diagonal resizing
  1117.             ModifyStyle(MFS_4THICKFRAME, 0);
  1118. #ifndef _SCB_MINIFRAME_CAPTION
  1119.             // remove caption
  1120.             ModifyStyle(WS_SYSMENU|WS_CAPTION, 0);
  1121. #endif
  1122.             DelayRecalcLayout();
  1123.             pBar->PostMessage(WM_NCPAINT);
  1124.         }
  1125.     }
  1126.     CMiniFrameWnd::OnWindowPosChanging(lpwndpos);
  1127. }
  1128. #endif //_SCB_REPLACE_MINIFRAME