sizecbar.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:44k
源码类别:

多媒体编程

开发平台:

Visual C++

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