home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / bardock.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  25KB  |  911 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE3_SEG
  14. #pragma code_seg(AFX_CORE3_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CDockBar
  26.  
  27. BEGIN_MESSAGE_MAP(CDockBar, CControlBar)
  28.     //{{AFX_MSG_MAP(CDockBar)
  29.     ON_WM_NCCALCSIZE()
  30.     ON_WM_NCPAINT()
  31.     ON_WM_WINDOWPOSCHANGING()
  32.     ON_WM_PAINT()
  33.     ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
  34.     //}}AFX_MSG_MAP
  35. END_MESSAGE_MAP()
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CDockBar construction
  39.  
  40. CDockBar::CDockBar(BOOL bFloating)
  41. {
  42.     m_bFloating = bFloating;
  43.     m_bAutoDelete = TRUE;
  44.     m_arrBars.Add(NULL);
  45.     m_bLayoutQuery = FALSE;
  46.     m_rectLayout.SetRectEmpty();
  47.  
  48.     // assume no margins
  49.     m_cxLeftBorder = m_cxRightBorder = m_cyBottomBorder = m_cyTopBorder = 0;
  50. }
  51.  
  52. CDockBar::~CDockBar()
  53. {
  54.     for (int i = 0; i < m_arrBars.GetSize(); i++)
  55.     {
  56.         CControlBar* pBar = GetDockedControlBar(i);
  57.         if (pBar != NULL && pBar->m_pDockBar == this)
  58.             pBar->m_pDockBar = NULL;
  59.     }
  60. }
  61.  
  62. BOOL CDockBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
  63. {
  64.     ASSERT(pParentWnd != NULL);
  65.     ASSERT_KINDOF(CFrameWnd, pParentWnd);
  66.  
  67.     // save the style
  68.     m_dwStyle = (dwStyle & CBRS_ALL);
  69.  
  70.     VERIFY(AfxDeferRegisterClass(AFX_WNDCONTROLBAR_REG));
  71.  
  72.     // create the HWND
  73.     CRect rect;
  74.     rect.SetRectEmpty();
  75.  
  76.     // Note: Parent must resize itself for control bar to be resized
  77.     return CWnd::Create(_afxWndControlBar, NULL, dwStyle, rect, pParentWnd, nID);
  78. }
  79.  
  80. BOOL CDockBar::IsDockBar() const
  81. {
  82.     return TRUE;
  83. }
  84.  
  85. int CDockBar::GetDockedCount() const
  86. {
  87.     int nCount = 0;
  88.     for (int i = 0; i < m_arrBars.GetSize(); i++)
  89.     {
  90.         if (GetDockedControlBar(i) != NULL)
  91.             nCount++;
  92.     }
  93.     return nCount;
  94. }
  95.  
  96. int CDockBar::GetDockedVisibleCount() const
  97. {
  98.     int nCount = 0;
  99.     for (int i = 0; i < m_arrBars.GetSize(); i++)
  100.     {
  101.         CControlBar* pBar = STATIC_DOWNCAST(CControlBar, (CObject*)GetDockedControlBar(i));
  102.         if (pBar != NULL && pBar->IsVisible())
  103.             nCount++;
  104.     }
  105.     return nCount;
  106. }
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. // CDockBar operations
  110.  
  111. void CDockBar::DockControlBar(CControlBar* pBar, LPCRECT lpRect)
  112. {
  113.     ASSERT_VALID(this);
  114.     ASSERT_VALID(pBar);
  115.     ASSERT_KINDOF(CControlBar, pBar);
  116.  
  117.     CRect rectBar;
  118.     pBar->GetWindowRect(&rectBar);
  119.     if (pBar->m_pDockBar == this && (lpRect == NULL || rectBar == *lpRect))
  120.     {
  121.         // already docked and no change in position
  122.         return;
  123.     }
  124.  
  125.     // set CBRS_FLOAT_MULTI style if docking bar has it
  126.     if (m_bFloating && (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI))
  127.         m_dwStyle |= CBRS_FLOAT_MULTI;
  128.  
  129.     m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
  130.     m_dwStyle |= pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
  131.  
  132.     if (!(m_dwStyle & CBRS_FLOAT_MULTI))
  133.     {
  134.         TCHAR szTitle[_MAX_PATH];
  135.         pBar->GetWindowText(szTitle, _countof(szTitle));
  136.         AfxSetWindowText(m_hWnd, szTitle);
  137.     }
  138.  
  139.     // align correctly and turn on all borders
  140.     DWORD dwStyle = pBar->GetBarStyle();
  141.     dwStyle &= ~(CBRS_ALIGN_ANY);
  142.     dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;
  143.  
  144.     if (m_bFloating)
  145.         dwStyle |= CBRS_FLOATING;
  146.     else
  147.         dwStyle &= ~CBRS_FLOATING;
  148.  
  149.     pBar->SetBarStyle(dwStyle);
  150.  
  151.     // hide first if changing to a new docking site to avoid flashing
  152.     BOOL bShow = FALSE;
  153.     if (pBar->m_pDockBar != this && pBar->IsWindowVisible())
  154.     {
  155.         pBar->SetWindowPos(NULL, 0, 0, 0, 0,
  156.             SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW);
  157.         bShow = TRUE;
  158.     }
  159.  
  160.     int nPos = -1;
  161.     if (lpRect != NULL)
  162.     {
  163.         // insert into appropriate row
  164.         CRect rect(lpRect);
  165.         ScreenToClient(&rect);
  166.         CPoint ptMid(rect.left + rect.Width()/2, rect.top + rect.Height()/2);
  167.         nPos = Insert(pBar, rect, ptMid);
  168.  
  169.         // position at requested position
  170.         pBar->SetWindowPos(NULL, rect.left, rect.top, rect.Width(),
  171.             rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
  172.     }
  173.     else
  174.     {
  175.         // always add on current row, then create new one
  176.         m_arrBars.Add(pBar);
  177.         m_arrBars.Add(NULL);
  178.  
  179.         // align off the edge initially
  180.         pBar->SetWindowPos(NULL, -afxData.cxBorder2, -afxData.cyBorder2, 0, 0,
  181.             SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
  182.     }
  183.  
  184.     // attach it to the docking site
  185.     if (pBar->GetParent() != this)
  186.         pBar->SetParent(this);
  187.     if (pBar->m_pDockBar == this)
  188.         pBar->m_pDockBar->RemoveControlBar(pBar, nPos);
  189.     else if (pBar->m_pDockBar != NULL)
  190.         pBar->m_pDockBar->RemoveControlBar(pBar, -1, m_bFloating && !pBar->m_pDockBar->m_bFloating);
  191.     pBar->m_pDockBar = this;
  192.  
  193.     if (bShow)
  194.     {
  195.         ASSERT(!pBar->IsWindowVisible());
  196.         pBar->SetWindowPos(NULL, 0, 0, 0, 0,
  197.             SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
  198.     }
  199.  
  200.     // remove any place holder for pBar in this dockbar
  201.     RemovePlaceHolder(pBar);
  202.  
  203.     // get parent frame for recalc layout
  204.     CFrameWnd* pFrameWnd = GetDockingFrame();
  205.     pFrameWnd->DelayRecalcLayout();
  206. }
  207.  
  208. void CDockBar::ReDockControlBar(CControlBar* pBar, LPCRECT lpRect)
  209. {
  210.     ASSERT_VALID(this);
  211.     ASSERT_VALID(pBar);
  212.     ASSERT_KINDOF(CControlBar, pBar);
  213.     ASSERT(pBar->m_pDockBar != this); // can't redock here if already docked here
  214.  
  215.     CRect rectBar;
  216.     pBar->GetWindowRect(&rectBar);
  217.     if (pBar->m_pDockBar == this && (lpRect == NULL || rectBar == *lpRect))
  218.     {
  219.         // already docked and no change in position
  220.         return;
  221.     }
  222.  
  223.     // set CBRS_FLOAT_MULTI style if docking bar has it
  224.     if (m_bFloating && (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI))
  225.         m_dwStyle |= CBRS_FLOAT_MULTI;
  226.  
  227.     m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
  228.     m_dwStyle |= pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
  229.  
  230.     if (!(m_dwStyle & CBRS_FLOAT_MULTI))
  231.     {
  232.         TCHAR szTitle[_MAX_PATH];
  233.         pBar->GetWindowText(szTitle, _countof(szTitle));
  234.         AfxSetWindowText(m_hWnd, szTitle);
  235.     }
  236.  
  237.     // align correctly and turn on all borders
  238.     DWORD dwStyle = pBar->GetBarStyle();
  239.     dwStyle &= ~(CBRS_ALIGN_ANY);
  240.     dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;
  241.  
  242.     if (m_bFloating)
  243.         dwStyle |= CBRS_FLOATING;
  244.     else
  245.         dwStyle &= ~CBRS_FLOATING;
  246.  
  247.     pBar->SetBarStyle(dwStyle);
  248.  
  249.     int nPos = FindBar((CControlBar*)_AfxGetDlgCtrlID(pBar->m_hWnd));
  250.     if (nPos > 0)
  251.         m_arrBars[nPos] = pBar;
  252.  
  253.     if (lpRect != NULL)
  254.     {
  255.         CRect rect(lpRect);
  256.         ScreenToClient(&rect);
  257.  
  258.         if (nPos < 1)
  259.         {
  260.             CPoint ptMid(rect.left + rect.Width()/2, rect.top + rect.Height()/2);
  261.             nPos = Insert(pBar, rect, ptMid);
  262.         }
  263.  
  264.         // position at requested position
  265.         pBar->SetWindowPos(NULL, rect.left, rect.top, rect.Width(),
  266.             rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
  267.     }
  268.     else
  269.     {
  270.         if (nPos < 1)
  271.         {
  272.             // always add on current row, then create new one
  273.             m_arrBars.Add(pBar);
  274.             m_arrBars.Add(NULL);
  275.         }
  276.  
  277.         // align off the edge initially
  278.         pBar->SetWindowPos(NULL, -afxData.cxBorder2, -afxData.cyBorder2, 0, 0,
  279.             SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
  280.     }
  281.  
  282.     // attach it to the docking site
  283.     if (pBar->GetParent() != this)
  284.         pBar->SetParent(this);
  285.     if (pBar->m_pDockBar != NULL)
  286.         pBar->m_pDockBar->RemoveControlBar(pBar);
  287.     pBar->m_pDockBar = this;
  288.  
  289.     // get parent frame for recalc layout
  290.     CFrameWnd* pFrameWnd = GetDockingFrame();
  291.     pFrameWnd->DelayRecalcLayout();
  292. }
  293.  
  294. void CDockBar::RemovePlaceHolder(CControlBar* pBar)
  295. {
  296.     // remove remembered docking position
  297.     if (HIWORD(pBar) != 0)
  298.         pBar = (CControlBar*)_AfxGetDlgCtrlID(pBar->m_hWnd);
  299.     int nOldPos = FindBar(pBar);
  300.     if (nOldPos > 0)
  301.     {
  302.         m_arrBars.RemoveAt(nOldPos);
  303.  
  304.         // remove section indicator (NULL) if nothing else in section
  305.         if (m_arrBars[nOldPos-1] == NULL && m_arrBars[nOldPos] == NULL)
  306.             m_arrBars.RemoveAt(nOldPos);
  307.     }
  308. }
  309.  
  310. BOOL CDockBar::RemoveControlBar(CControlBar* pBar, int nPosExclude, int nAddPlaceHolder)
  311. {
  312.     ASSERT(nAddPlaceHolder == 1 || nAddPlaceHolder == 0 || nAddPlaceHolder == -1);
  313.     ASSERT_VALID(this);
  314.     ASSERT(pBar != NULL);
  315.     int nPos = FindBar(pBar, nPosExclude);
  316.     ASSERT(nPos > 0);
  317.  
  318.     if (nAddPlaceHolder == 1)
  319.     {
  320.         m_arrBars[nPos] = (void*)_AfxGetDlgCtrlID(pBar->m_hWnd);
  321.  
  322.         // check for already existing place holder
  323.         int nPosOld = FindBar((CControlBar*)m_arrBars[nPos], nPos);
  324.         if (nPosOld > 0)
  325.         {
  326.             m_arrBars.RemoveAt(nPos);
  327.  
  328.             // remove section indicator (NULL) if nothing else in section
  329.             if (m_arrBars[nPos-1] == NULL && m_arrBars[nPos] == NULL)
  330.                 m_arrBars.RemoveAt(nPos);
  331.         }
  332.     }
  333.     else
  334.     {
  335.         m_arrBars.RemoveAt(nPos);
  336.         if (m_arrBars[nPos-1] == NULL && m_arrBars[nPos] == NULL)
  337.             m_arrBars.RemoveAt(nPos);
  338.  
  339.         // Remove any pre-existing place holders.
  340.         if (nAddPlaceHolder != -1)
  341.             RemovePlaceHolder(pBar);
  342.     }
  343.  
  344.     // don't do anything more in the shutdown case!
  345.     if (pBar->m_pDockContext == NULL)
  346.         return FALSE;
  347.  
  348.     // get parent frame for recalc layout/frame destroy
  349.     CFrameWnd* pFrameWnd = GetDockingFrame();
  350.     if (m_bFloating && GetDockedVisibleCount() == 0)
  351.     {
  352.         if (GetDockedCount() == 0)
  353.         {
  354.             pFrameWnd->DestroyWindow();
  355.             return TRUE; // Self-Destruct
  356.         }
  357.         else
  358.             pFrameWnd->ShowWindow(SW_HIDE);
  359.     }
  360.     else
  361.         pFrameWnd->DelayRecalcLayout();
  362.  
  363.     return FALSE;
  364. }
  365.  
  366. /////////////////////////////////////////////////////////////////////////////
  367. // CDockBar layout
  368.  
  369. CSize CDockBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  370. {
  371.     ASSERT_VALID(this);
  372.  
  373.     CSize sizeFixed = CControlBar::CalcFixedLayout(bStretch, bHorz);
  374.  
  375.     // get max size
  376.     CSize sizeMax;
  377.     if (!m_rectLayout.IsRectEmpty())
  378.         sizeMax = m_rectLayout.Size();
  379.     else
  380.     {
  381.         CRect rectFrame;
  382.         CFrameWnd* pFrame = GetParentFrame();
  383.         pFrame->GetClientRect(&rectFrame);
  384.         sizeMax = rectFrame.Size();
  385.     }
  386.  
  387.     // prepare for layout
  388.     AFX_SIZEPARENTPARAMS layout;
  389.     layout.hDWP = m_bLayoutQuery ?
  390.         NULL : ::BeginDeferWindowPos(m_arrBars.GetSize());
  391.     CPoint pt(-afxData.cxBorder2, -afxData.cyBorder2);
  392.     int nWidth = 0;
  393.  
  394.     BOOL bWrapped = FALSE;
  395.  
  396.     // layout all the control bars
  397.     for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
  398.     {
  399.         CControlBar* pBar = GetDockedControlBar(nPos);
  400.         void* pVoid = m_arrBars[nPos];
  401.  
  402.         if (pBar != NULL)
  403.         {
  404.             if (pBar->IsVisible())
  405.             {
  406.                 // get ideal rect for bar
  407.                 DWORD dwMode = 0;
  408.                 if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) &&
  409.                     (pBar->m_dwStyle & CBRS_FLOATING))
  410.                     dwMode |= LM_HORZ | LM_MRUWIDTH;
  411.                 else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
  412.                     dwMode |= LM_HORZ | LM_HORZDOCK;
  413.                 else
  414.                     dwMode |=  LM_VERTDOCK;
  415.  
  416.                 CSize sizeBar = pBar->CalcDynamicLayout(-1, dwMode);
  417.  
  418.                 CRect rect(pt, sizeBar);
  419.  
  420.                 // get current rect for bar
  421.                 CRect rectBar;
  422.                 pBar->GetWindowRect(&rectBar);
  423.                 ScreenToClient(&rectBar);
  424.  
  425.                 if (bHorz)
  426.                 {
  427.                     // Offset Calculated Rect out to Actual
  428.                     if (rectBar.left > rect.left && !m_bFloating)
  429.                         rect.OffsetRect(rectBar.left - rect.left, 0);
  430.  
  431.                     // If ControlBar goes off the right, then right justify
  432.                     if (rect.right > sizeMax.cx && !m_bFloating)
  433.                     {
  434.                         int x = rect.Width() - afxData.cxBorder2;
  435.                         x = max(sizeMax.cx - x, pt.x);
  436.                         rect.OffsetRect(x - rect.left, 0);
  437.                     }
  438.  
  439.                     // If ControlBar has been wrapped, then left justify
  440.                     if (bWrapped)
  441.                     {
  442.                         bWrapped = FALSE;
  443.                         rect.OffsetRect(-(rect.left + afxData.cxBorder2), 0);
  444.                     }
  445.                     // If ControlBar is completely invisible, then wrap it
  446.                     else if ((rect.left >= (sizeMax.cx - afxData.cxBorder2)) &&
  447.                         (nPos > 0) && (m_arrBars[nPos - 1] != NULL))
  448.                     {
  449.                         m_arrBars.InsertAt(nPos, (CObject*)NULL);
  450.                         pBar = NULL; pVoid = NULL;
  451.                         bWrapped = TRUE;
  452.                     }
  453.                     if (!bWrapped)
  454.                     {
  455.                         if (rect != rectBar)
  456.                         {
  457.                             if (!m_bLayoutQuery &&
  458.                                 !(pBar->m_dwStyle & CBRS_FLOATING))
  459.                             {
  460.                                 pBar->m_pDockContext->m_rectMRUDockPos = rect;
  461.                             }
  462.                             AfxRepositionWindow(&layout, pBar->m_hWnd, &rect);
  463.                         }
  464.                         pt.x = rect.left + sizeBar.cx - afxData.cxBorder2;
  465.                         nWidth = max(nWidth, sizeBar.cy);
  466.                     }
  467.                 }
  468.                 else
  469.                 {
  470.                     // Offset Calculated Rect out to Actual
  471.                     if (rectBar.top > rect.top && !m_bFloating)
  472.                         rect.OffsetRect(0, rectBar.top - rect.top);
  473.  
  474.                     // If ControlBar goes off the bottom, then bottom justify
  475.                     if (rect.bottom > sizeMax.cy && !m_bFloating)
  476.                     {
  477.                         int y = rect.Height() - afxData.cyBorder2;
  478.                         y = max(sizeMax.cy - y, pt.y);
  479.                         rect.OffsetRect(0, y - rect.top);
  480.                     }
  481.  
  482.                     // If ControlBar has been wrapped, then top justify
  483.                     if (bWrapped)
  484.                     {
  485.                         bWrapped = FALSE;
  486.                         rect.OffsetRect(0, -(rect.top + afxData.cyBorder2));
  487.                     }
  488.                     // If ControlBar is completely invisible, then wrap it
  489.                     else if ((rect.top >= (sizeMax.cy - afxData.cyBorder2)) &&
  490.                         (nPos > 0) && (m_arrBars[nPos - 1] != NULL))
  491.                     {
  492.                         m_arrBars.InsertAt(nPos, (CObject*)NULL);
  493.                         pBar = NULL; pVoid = NULL;
  494.                         bWrapped = TRUE;
  495.                     }
  496.                     if (!bWrapped)
  497.                     {
  498.                         if (rect != rectBar)
  499.                         {
  500.                             if (!m_bLayoutQuery &&
  501.                                 !(pBar->m_dwStyle & CBRS_FLOATING))
  502.                             {
  503.                                 pBar->m_pDockContext->m_rectMRUDockPos = rect;
  504.                             }
  505.                             AfxRepositionWindow(&layout, pBar->m_hWnd, &rect);
  506.                         }
  507.                         pt.y = rect.top + sizeBar.cy - afxData.cyBorder2;
  508.                         nWidth = max(nWidth, sizeBar.cx);
  509.                     }
  510.                 }
  511.             }
  512.             if (!bWrapped)
  513.             {
  514.                 // handle any delay/show hide for the bar
  515.                 pBar->RecalcDelayShow(&layout);
  516.             }
  517.         }
  518.         if (pBar == NULL && pVoid == NULL && nWidth != 0)
  519.         {
  520.             // end of row because pBar == NULL
  521.             if (bHorz)
  522.             {
  523.                 pt.y += nWidth - afxData.cyBorder2;
  524.                 sizeFixed.cx = max(sizeFixed.cx, pt.x);
  525.                 sizeFixed.cy = max(sizeFixed.cy, pt.y);
  526.                 pt.x = -afxData.cxBorder2;
  527.             }
  528.             else
  529.             {
  530.                 pt.x += nWidth - afxData.cxBorder2;
  531.                 sizeFixed.cx = max(sizeFixed.cx, pt.x);
  532.                 sizeFixed.cy = max(sizeFixed.cy, pt.y);
  533.                 pt.y = -afxData.cyBorder2;
  534.             }
  535.             nWidth = 0;
  536.         }
  537.     }
  538.     if (!m_bLayoutQuery)
  539.     {
  540.         // move and resize all the windows at once!
  541.         if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  542.             TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
  543.     }
  544.  
  545.     // adjust size for borders on the dock bar itself
  546.     CRect rect;
  547.     rect.SetRectEmpty();
  548.     CalcInsideRect(rect, bHorz);
  549.  
  550.     if ((!bStretch || !bHorz) && sizeFixed.cx != 0)
  551.         sizeFixed.cx += -rect.right + rect.left;
  552.     if ((!bStretch || bHorz) && sizeFixed.cy != 0)
  553.         sizeFixed.cy += -rect.bottom + rect.top;
  554.  
  555.     return sizeFixed;
  556. }
  557.  
  558. LRESULT CDockBar::OnSizeParent(WPARAM wParam, LPARAM lParam)
  559. {
  560.     AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
  561.  
  562.     // set m_bLayoutQuery to TRUE if lpLayout->hDWP == NULL
  563.     BOOL bLayoutQuery = m_bLayoutQuery;
  564.     CRect rectLayout = m_rectLayout;
  565.     m_bLayoutQuery = (lpLayout->hDWP == NULL);
  566.     m_rectLayout = lpLayout->rect;
  567.     LRESULT lResult = CControlBar::OnSizeParent(wParam, lParam);
  568.     // restore m_bLayoutQuery
  569.     m_bLayoutQuery = bLayoutQuery;
  570.     m_rectLayout = rectLayout;
  571.  
  572.     return lResult;
  573. }
  574.  
  575. /////////////////////////////////////////////////////////////////////////////
  576. // CDockBar message handlers
  577.  
  578. void CDockBar::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS* lpncsp)
  579. {
  580.     // calculate border space (will add to top/bottom, subtract from right/bottom)
  581.     CRect rect;
  582.     rect.SetRectEmpty();
  583.     CalcInsideRect(rect, m_dwStyle & CBRS_ORIENT_HORZ);
  584.  
  585.     // adjust non-client area for border space
  586.     lpncsp->rgrc[0].left += rect.left;
  587.     lpncsp->rgrc[0].top += rect.top;
  588.     lpncsp->rgrc[0].right += rect.right;
  589.     lpncsp->rgrc[0].bottom += rect.bottom;
  590. }
  591.  
  592. void CDockBar::OnNcPaint()
  593. {
  594.     EraseNonClient();
  595. }
  596.  
  597. void CDockBar::DoPaint(CDC*)
  598. {
  599.     // border painting is done in non-client area
  600. }
  601.  
  602. void CDockBar::OnPaint()
  603. {
  604.     // background is already filled in gray
  605.     CPaintDC dc(this);
  606.     if (IsVisible() && GetDockedVisibleCount() != 0)
  607.         DoPaint(&dc);       // delegate to paint helper
  608. }
  609.  
  610. void CDockBar::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
  611. {
  612.     // not necessary to invalidate the borders
  613.     DWORD dwStyle = m_dwStyle;
  614.     m_dwStyle &= ~(CBRS_BORDER_ANY);
  615.     CControlBar::OnWindowPosChanging(lpWndPos);
  616.     m_dwStyle = dwStyle;
  617. }
  618.  
  619. /////////////////////////////////////////////////////////////////////////////
  620. // CDockBar utility/implementation
  621.  
  622. int CDockBar::FindBar(CControlBar* pBar, int nPosExclude)
  623. {
  624.     for (int nPos = 0; nPos< m_arrBars.GetSize(); nPos++)
  625.     {
  626.         if (nPos != nPosExclude && m_arrBars[nPos] == pBar)
  627.             return nPos;
  628.     }
  629.     return -1;
  630. }
  631.  
  632. void CDockBar::ShowAll(BOOL bShow)
  633. {
  634.     for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
  635.     {
  636.         CControlBar* pBar = GetDockedControlBar(nPos);
  637.         if (pBar != NULL)
  638.         {
  639.             CFrameWnd* pFrameWnd = pBar->GetDockingFrame();
  640.             pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
  641.         }
  642.     }
  643. }
  644.  
  645. CControlBar* CDockBar::GetDockedControlBar(int nPos) const
  646. {
  647.     CControlBar* pResult = (CControlBar*)m_arrBars[nPos];
  648.     if (HIWORD(pResult) == 0)
  649.         return NULL;
  650.     return pResult;
  651. }
  652.  
  653. int CDockBar::Insert(CControlBar* pBarIns, CRect rect, CPoint ptMid)
  654. {
  655.     ASSERT_VALID(this);
  656.     ASSERT(pBarIns != NULL);
  657.  
  658.     int nPos = 0;
  659.     int nPosInsAfter = 0;
  660.     int nWidth = 0;
  661.     int nTotalWidth = 0;
  662.     BOOL bHorz = m_dwStyle & CBRS_ORIENT_HORZ;
  663.  
  664.     for (nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
  665.     {
  666.         CControlBar* pBar = GetDockedControlBar(nPos);
  667.         if (pBar != NULL && pBar->IsVisible())
  668.         {
  669.             CRect rectBar;
  670.             pBar->GetWindowRect(&rectBar);
  671.             ScreenToClient(&rectBar);
  672.             nWidth = max(nWidth,
  673.                 bHorz ? rectBar.Size().cy : rectBar.Size().cx - 1);
  674.             if (bHorz ? rect.left > rectBar.left : rect.top > rectBar.top)
  675.                 nPosInsAfter = nPos;
  676.         }
  677.         else // end of row because pBar == NULL
  678.         {
  679.             nTotalWidth += nWidth - afxData.cyBorder2;
  680.             nWidth = 0;
  681.             if ((bHorz ? ptMid.y : ptMid.x) < nTotalWidth)
  682.             {
  683.                 if (nPos == 0) // first section
  684.                     m_arrBars.InsertAt(nPosInsAfter+1, (CObject*)NULL);
  685.                 m_arrBars.InsertAt(nPosInsAfter+1, pBarIns);
  686.                 return nPosInsAfter+1;
  687.             }
  688.             nPosInsAfter = nPos;
  689.         }
  690.     }
  691.  
  692.     // create a new row
  693.     m_arrBars.InsertAt(nPosInsAfter+1, (CObject*)NULL);
  694.     m_arrBars.InsertAt(nPosInsAfter+1, pBarIns);
  695.  
  696.     return nPosInsAfter+1;
  697. }
  698.  
  699. void CDockBar::OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL /*bDisableIfNoHndler*/)
  700. {
  701. }
  702.  
  703. #ifdef _DEBUG
  704. void CDockBar::AssertValid() const
  705. {
  706.     CControlBar::AssertValid();
  707.     ASSERT(m_arrBars.GetSize() != 0);
  708.     ASSERT(m_arrBars[0] == NULL);
  709.     ASSERT(m_arrBars[m_arrBars.GetUpperBound()] == NULL);
  710. }
  711.  
  712. void CDockBar::Dump(CDumpContext& dc) const
  713. {
  714.     CControlBar::Dump(dc);
  715.  
  716.     dc << "m_arrBars " << m_arrBars;
  717.     dc << "\nm_bFloating " << m_bFloating;
  718.  
  719.     dc << "\n";
  720. }
  721. #endif
  722.  
  723. /////////////////////////////////////////////////////////////////////////////
  724. // CControlBar docking helpers
  725.  
  726. void CControlBar::EnableDocking(DWORD dwDockStyle)
  727. {
  728.     // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  729.     ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
  730.     // CBRS_SIZE_DYNAMIC toolbar cannot have the CBRS_FLOAT_MULTI style
  731.     ASSERT(((dwDockStyle & CBRS_FLOAT_MULTI) == 0) || ((m_dwStyle & CBRS_SIZE_DYNAMIC) == 0));
  732.  
  733.     m_dwDockStyle = dwDockStyle;
  734.     if (m_pDockContext == NULL)
  735.         m_pDockContext = new CDockContext(this);
  736.  
  737.     // permanently wire the bar's owner to its current parent
  738.     if (m_hWndOwner == NULL)
  739.         m_hWndOwner = ::GetParent(m_hWnd);
  740. }
  741.  
  742. /////////////////////////////////////////////////////////////////////////////
  743. // CMiniDockFrameWnd
  744.  
  745. BEGIN_MESSAGE_MAP(CMiniDockFrameWnd, CMiniFrameWnd)
  746.     //{{AFX_MSG_MAP(CMiniDockFrameWnd)
  747.     ON_WM_CLOSE()
  748.     ON_WM_NCLBUTTONDOWN()
  749.     ON_WM_NCLBUTTONDBLCLK()
  750.     //}}AFX_MSG_MAP
  751.     ON_WM_MOUSEACTIVATE()
  752. END_MESSAGE_MAP()
  753.  
  754. int CMiniDockFrameWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
  755. {
  756.     if (nHitTest >= HTSIZEFIRST && nHitTest <= HTSIZELAST) // resizing
  757.         return MA_NOACTIVATE;
  758.     return CMiniFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
  759. }
  760.  
  761. CMiniDockFrameWnd::CMiniDockFrameWnd() : m_wndDockBar(TRUE)
  762. {
  763.     m_wndDockBar.m_bAutoDelete = FALSE;
  764. }
  765.  
  766. BOOL CMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
  767. {
  768.     // set m_bInRecalcLayout to avoid flashing during creation
  769.     // RecalcLayout will be called once something is docked
  770.     m_bInRecalcLayout = TRUE;
  771.  
  772.     DWORD dwStyle = WS_POPUP|WS_CAPTION|WS_SYSMENU|MFS_MOVEFRAME|
  773.         MFS_4THICKFRAME|MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|
  774.         FWS_SNAPTOBARS;
  775.  
  776.     if (dwBarStyle & CBRS_SIZE_DYNAMIC)
  777.         dwStyle &= ~MFS_MOVEFRAME;
  778.  
  779.     DWORD dwExStyle = 0;
  780.     if (!CMiniFrameWnd::CreateEx(dwExStyle,
  781.         NULL, &afxChNil, dwStyle, rectDefault, pParent))
  782.     {
  783.         m_bInRecalcLayout = FALSE;
  784.         return FALSE;
  785.     }
  786.     dwStyle = dwBarStyle & (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ?
  787.         CBRS_ALIGN_LEFT : CBRS_ALIGN_TOP;
  788.     dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI;
  789.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  790.     pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);
  791.     pSysMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);
  792.     pSysMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);
  793.     pSysMenu->DeleteMenu(SC_RESTORE, MF_BYCOMMAND);
  794.     CString strHide;
  795.     if (strHide.LoadString(AFX_IDS_HIDE))
  796.     {
  797.         pSysMenu->DeleteMenu(SC_CLOSE, MF_BYCOMMAND);
  798.         pSysMenu->AppendMenu(MF_STRING|MF_ENABLED, SC_CLOSE, strHide);
  799.     }
  800.  
  801.     // must initially create with parent frame as parent
  802.     if (!m_wndDockBar.Create(pParent, WS_CHILD | WS_VISIBLE | dwStyle,
  803.         AFX_IDW_DOCKBAR_FLOAT))
  804.     {
  805.         m_bInRecalcLayout = FALSE;
  806.         return FALSE;
  807.     }
  808.  
  809.     // set parent to CMiniDockFrameWnd
  810.     m_wndDockBar.SetParent(this);
  811.     m_bInRecalcLayout = FALSE;
  812.  
  813.     return TRUE;
  814. }
  815.  
  816. void CMiniDockFrameWnd::RecalcLayout(BOOL bNotify)
  817. {
  818.     if (!m_bInRecalcLayout)
  819.     {
  820.         CMiniFrameWnd::RecalcLayout(bNotify);
  821.  
  822.         // syncronize window text of frame window with dockbar itself
  823.         TCHAR szTitle[_MAX_PATH];
  824.         m_wndDockBar.GetWindowText(szTitle, _countof(szTitle));
  825.         AfxSetWindowText(m_hWnd, szTitle);
  826.     }
  827. }
  828.  
  829. void CMiniDockFrameWnd::OnClose()
  830. {
  831.     m_wndDockBar.ShowAll(FALSE);
  832. }
  833.  
  834. void CMiniDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
  835. {
  836.     if (nHitTest == HTCAPTION)
  837.     {
  838.         // special activation for floating toolbars
  839.         ActivateTopParent();
  840.  
  841.         // initiate toolbar drag for non-CBRS_FLOAT_MULTI toolbars
  842.         if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0)
  843.         {
  844.             int nPos = 1;
  845.             CControlBar* pBar = NULL;
  846.             while(pBar == NULL && nPos < m_wndDockBar.m_arrBars.GetSize())
  847.                 pBar = m_wndDockBar.GetDockedControlBar(nPos++);
  848.  
  849.             ASSERT(pBar != NULL);
  850.             ASSERT_KINDOF(CControlBar, pBar);
  851.             ASSERT(pBar->m_pDockContext != NULL);
  852.             pBar->m_pDockContext->StartDrag(point);
  853.             return;
  854.         }
  855.     }
  856.     else if (nHitTest >= HTSIZEFIRST && nHitTest <= HTSIZELAST)
  857.     {
  858.         // special activation for floating toolbars
  859.         ActivateTopParent();
  860.  
  861.         int nPos = 1;
  862.         CControlBar* pBar = NULL;
  863.         while(pBar == NULL && nPos < m_wndDockBar.m_arrBars.GetSize())
  864.             pBar = m_wndDockBar.GetDockedControlBar(nPos++);
  865.  
  866.         ASSERT(pBar != NULL);
  867.         ASSERT_KINDOF(CControlBar, pBar);
  868.         ASSERT(pBar->m_pDockContext != NULL);
  869.  
  870.         // CBRS_SIZE_DYNAMIC toolbars cannot have the CBRS_FLOAT_MULTI style
  871.         ASSERT((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0);
  872.         pBar->m_pDockContext->StartResize(nHitTest, point);
  873.         return;
  874.     }
  875.     CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
  876. }
  877.  
  878. void CMiniDockFrameWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
  879. {
  880.     if (nHitTest == HTCAPTION)
  881.     {
  882.         // special activation for floating toolbars
  883.         ActivateTopParent();
  884.  
  885.         // initiate toolbar toggle for non-CBRS_FLOAT_MULTI toolbars
  886.         if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0)
  887.         {
  888.             int nPos = 1;
  889.             CControlBar* pBar = NULL;
  890.             while(pBar == NULL && nPos < m_wndDockBar.m_arrBars.GetSize())
  891.                 pBar = m_wndDockBar.GetDockedControlBar(nPos++);
  892.  
  893.             ASSERT(pBar != NULL);
  894.             ASSERT_KINDOF(CControlBar, pBar);
  895.             ASSERT(pBar->m_pDockContext != NULL);
  896.             pBar->m_pDockContext->ToggleDocking();
  897.             return;
  898.         }
  899.     }
  900.     CMiniFrameWnd::OnNcLButtonDblClk(nHitTest, point);
  901. }
  902.  
  903. #ifdef AFX_INIT_SEG
  904. #pragma code_seg(AFX_INIT_SEG)
  905. #endif
  906.  
  907. IMPLEMENT_DYNAMIC(CDockBar, CControlBar)
  908. IMPLEMENT_DYNCREATE(CMiniDockFrameWnd, CMiniFrameWnd)
  909.  
  910. /////////////////////////////////////////////////////////////////////////////
  911.