home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / MINSPLIT.ZIP / MinSplitterWnd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-11  |  18.1 KB  |  663 lines

  1. // MinSplitterWnd.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include <afxpriv.h>            //    For AFX_SIZEPARENTPARAMS and AfxRepositionWindow
  6. #include "MinSplitterWnd.h"
  7.  
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13.  
  14. //==============================================================================
  15. //
  16. //    Kludges because we don't have access to mfc\src.
  17. //
  18. //==============================================================================
  19.  
  20. //    From afximpl.h and auxdata.cpp
  21.  
  22. // Note: afxData.cxBorder and afxData.cyBorder aren't used anymore
  23. #define CX_BORDER   1
  24. #define CY_BORDER   1
  25.  
  26. struct _AFXDATA
  27. {
  28.     int cxBorder2, cyBorder2;
  29.     BOOL    bWin4;          // TRUE if Windows 4.0
  30.     BOOL    bNotWin4;       // TRUE if not Windows 4.0
  31.  
  32.     _AFXDATA()    //    From auxdata.cpp
  33.     {
  34.         // Cache various target platform version information
  35.         DWORD dwVersion = ::GetVersion();
  36.         bWin4 = (BYTE)dwVersion >= 4;
  37.         bNotWin4 = 1 - bWin4;   // for convenience
  38.  
  39.         // cxBorder2 and cyBorder are 2x borders for Win4
  40.         cxBorder2 = bWin4 ? CX_BORDER*2 : CX_BORDER;
  41.         cyBorder2 = bWin4 ? CY_BORDER*2 : CY_BORDER;
  42.     }
  43. } afxData;
  44.  
  45. //    From winsplit.cpp...
  46.  
  47. // HitTest return values (values and spacing between values is important)
  48. enum HitTestValue
  49. {
  50.     noHit                   = 0,
  51.     vSplitterBox            = 1,
  52.     hSplitterBox            = 2,
  53.     bothSplitterBox         = 3,        // just for keyboard
  54.     vSplitterBar1           = 101,
  55.     vSplitterBar15          = 115,
  56.     hSplitterBar1           = 201,
  57.     hSplitterBar15          = 215,
  58.     splitterIntersection1   = 301,
  59.     splitterIntersection225 = 525
  60. };
  61.  
  62. //==============================================================================
  63. //
  64. //    End of Kludges.
  65. //
  66. //==============================================================================
  67.  
  68. /////////////////////////////////////////////////////////////////////////////
  69. // CMinSplitterWnd
  70.  
  71. CMinSplitterWnd::CMinSplitterWnd()
  72. {
  73. }
  74.  
  75. CMinSplitterWnd::~CMinSplitterWnd()
  76. {
  77. }
  78.  
  79.  
  80. BEGIN_MESSAGE_MAP(CMinSplitterWnd, CSplitterWnd)
  81.     //{{AFX_MSG_MAP(CMinSplitterWnd)
  82.     ON_WM_MOUSEMOVE()
  83.     ON_WM_WINDOWPOSCHANGING()
  84.     //}}AFX_MSG_MAP
  85. END_MESSAGE_MAP()
  86.  
  87.  
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CMinSplitterWnd message handlers
  90.  
  91. void CMinSplitterWnd::OnMouseMove(UINT nFlags, CPoint point) 
  92. {
  93.  
  94.     if ( m_bTracking && GetCapture() == this )
  95.     {
  96.         //    Work out which panes are left or above the splitter (horiz and vert).
  97.         bool    bSizingCol = false;
  98.         bool    bSizingRow = false;
  99.         int        nCol;
  100.         int        nRow;
  101.  
  102.         if ( m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15 )
  103.         {
  104.             nCol = m_htTrack - hSplitterBar1;
  105.             bSizingCol = true;
  106.         }
  107.         else if ( m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15 )
  108.         {
  109.             nRow = m_htTrack - vSplitterBar1;
  110.             bSizingRow = true;
  111.         }
  112.         else if ( m_htTrack >= splitterIntersection1 && m_htTrack <= splitterIntersection225 )
  113.         {
  114.             nCol = ( m_htTrack - splitterIntersection1 ) % 15;
  115.             nRow = ( m_htTrack - splitterIntersection1 ) / 15;
  116.             bSizingCol = true;
  117.             bSizingRow = true;
  118.         } // if
  119.  
  120.         //    Get client rect for limit calculations.
  121.         CRect rectClient;
  122.         GetClientRect( rectClient );
  123.  
  124.         point.Offset( m_ptTrackOffset ); // point is the upper right of hit detect
  125.  
  126.         //    Limit row.
  127.         if ( bSizingRow )
  128.         {
  129.             int nLimit1 = m_cyBorder;                    //    Start with top border.
  130.  
  131.             //    If top splitter...
  132.             if ( nRow == 0 )
  133.             {
  134.                 nLimit1 += m_pRowInfo[ 0 ].nMinSize;        //    ...just add first row minimum size.
  135.             }
  136.             //    If pane above splitter at minimum size...
  137.             else if ( m_pRowInfo[ nRow ].nCurSize == m_pRowInfo[ nRow ].nMinSize )
  138.             {
  139.                 for ( int i = 0; i < nRow; i++ )
  140.                 {
  141.                     nLimit1 += m_pRowInfo[ i ].nCurSize;    //    ...add previous rows' sizes and splitters.
  142.                     nLimit1 += m_cySplitter;
  143.                 } // for
  144.                 nLimit1 += m_pRowInfo[ i ].nCurSize;
  145.             }
  146.             //    Otherwise...
  147.             else
  148.             {
  149.                 for ( int i = 0; i < nRow; i++ )
  150.                 {
  151.                     nLimit1 += m_pRowInfo[ i ].nMinSize;    //    ...add previous rows' minimum sizes and splitters.
  152.                     nLimit1 += m_cySplitter;
  153.                 } // for
  154.                 nLimit1 += m_pRowInfo[ i ].nMinSize;
  155.             } // if
  156.  
  157.  
  158.             int nLimit2 = rectClient.bottom;            //    Start with bottom.
  159.             nLimit2 -= m_cyBorder;                        //    Take off bottom border.
  160.  
  161.             //    If bottom splitter...
  162.             if ( nRow + 1 == m_nRows - 1 )
  163.             {
  164.                 nLimit2 -= m_pRowInfo[ nRow + 1 ].nMinSize;    //    ...just take off last row minimum size.
  165.             }
  166.             //    Otherwise...
  167.             else
  168.             {
  169.                 for ( int i = m_nRows - 1; i > nRow + 1; i-- )
  170.                 {
  171.                     nLimit2 -= m_pRowInfo[ i ].nMinSize;    //    ...take off following rows' minimum sizes and splitters.
  172.                     nLimit2 -= m_cySplitter;
  173.                 } // for
  174.                 nLimit2 -= m_pRowInfo[ i ].nMinSize;
  175.             } // if
  176.  
  177.             nLimit2 -= m_cySplitter / 2;                //    Take off half a splitter.
  178.  
  179.             if ( point.y < nLimit1 + m_cySplitter / 2 - 2 )
  180.             {
  181.                 point.y = nLimit1 + m_cySplitter / 2 - 2;
  182.             } // if
  183.  
  184.             if ( point.y > nLimit2 - m_cySplitter / 2 )
  185.             {
  186.                 point.y = nLimit2 - m_cySplitter / 2;
  187.             } // if
  188.         } // if
  189.  
  190.         //    Limit column.
  191.         if ( bSizingCol )
  192.         {
  193.             int nLimit1 = 0;// = m_cxBorder;                    //    Start with left border.
  194.  
  195.             //    If left splitter...
  196.             if ( nCol == 0 )
  197.             {
  198.                 nLimit1 += m_pColInfo[ 0 ].nMinSize;        //    ...just add first column minimum size.
  199.             }
  200.             //    If pane left of splitter at minimum size...
  201.             else if ( m_pColInfo[ nCol ].nCurSize == m_pColInfo[ nCol ].nMinSize )
  202.             {
  203.                 for ( int i = 0; i < nCol; i++ )
  204.                 {
  205.                     nLimit1 += m_pColInfo[ i ].nCurSize;    //    ...add previous columns' sizes and splitters.
  206.                     nLimit1 += m_cxSplitter;
  207.                 } // for
  208.                 nLimit1 += m_pColInfo[ i ].nCurSize;
  209.             }
  210.             //    Otherwise...
  211.             else
  212.             {
  213.                 for ( int i = 0; i < nCol; i++ )
  214.                 {
  215.                     nLimit1 += m_pColInfo[ i ].nMinSize;    //    ...add previous columns' minimum sizes and splitters.
  216.                     nLimit1 += m_cxSplitter;
  217.                 } // for
  218.                 nLimit1 += m_pColInfo[ i ].nMinSize;    //    Minimum height of each column,
  219.             } // if
  220.  
  221.  
  222.             int nLimit2 = rectClient.right;                //    Start with right.
  223.             nLimit2 -= m_cxBorder;                        //    Take off right border,
  224.  
  225.             //    If right splitter...
  226.             if ( nCol + 1 == m_nCols - 1 )
  227.             {
  228.                 nLimit2 -= m_pColInfo[ nCol + 1 ].nMinSize;    //    ...just take off last column minimum size.
  229.             }
  230.             //    Otherwise...
  231.             else
  232.             {
  233.                 for ( int i = m_nCols - 1; i > nCol + 1; i-- )
  234.                 {
  235.                     nLimit2 -= m_pColInfo[ i ].nMinSize;    //    ...take off following columns' minimum sizes and splitters.
  236.                     nLimit2 -= m_cxSplitter;
  237.                 } // for
  238.                 nLimit2 -= m_pColInfo[ i ].nMinSize;
  239.             } // if
  240.  
  241.             nLimit2 -= m_cxSplitter / 2;                //    Take off half a splitter,
  242.  
  243.             if ( point.x < nLimit1/* + m_cxSplitter / 2 - 2*/ )
  244.             {
  245.                 point.x = nLimit1 /*+ m_cxSplitter / 2 - 2*/;
  246.             } // if
  247.             
  248.             if ( point.x > nLimit2 - m_cxSplitter / 2 )
  249.             {
  250.                 point.x = nLimit2 - m_cxSplitter / 2;
  251.             } // if
  252.         } // if
  253.  
  254.         //    Restore offset 'cos CSplitterWnd::OnMouseMove will do it again.
  255.         point.Offset( -m_ptTrackOffset ); // point is the upper right of hit detect
  256.     } // if
  257.  
  258.     //    Call base class.
  259.     CSplitterWnd::OnMouseMove(nFlags, point);
  260. }
  261.  
  262. int CMinSplitterWnd::GetMinClientWidth()
  263. {
  264.     //    If no columns, no width.
  265.     if ( m_pColInfo == NULL )
  266.     {
  267.         return 0;
  268.     } // if
  269.  
  270.     //    Min width is...
  271.     int nMinWidth = m_cxBorder;                        //    Left border,
  272.     
  273.     for ( int nCol = 0; nCol < m_nCols; nCol++ )
  274.     {
  275.         nMinWidth += m_pColInfo[ nCol ].nMinSize;    //    Minimum width of each column,
  276.  
  277.         if ( nCol < m_nCols - 1 )
  278.         {
  279.             nMinWidth += m_cxSplitter;                //    Width of splitter for each column except the last,
  280.         } // if
  281.     } // for
  282.  
  283.     nMinWidth += m_cxBorder;                        //    Right border.
  284.  
  285.     return nMinWidth;
  286. }
  287.  
  288. int CMinSplitterWnd::GetMinClientHeight()
  289. {
  290.     //    If no rows, no height.
  291.     if ( m_pRowInfo == NULL )
  292.     {
  293.         return 0;
  294.     } // if
  295.  
  296.     //    Min height is...
  297.     int nMinHeight = m_cyBorder;                    //    Top border,
  298.     
  299.     for ( int nRow = 0; nRow < m_nRows; nRow++ )
  300.     {
  301.         nMinHeight += m_pRowInfo[ nRow ].nMinSize;    //    Minimum height of each row,
  302.  
  303.         if ( nRow < m_nRows - 1 )
  304.         {
  305.             nMinHeight += m_cySplitter;                //    Height of splitter for each row except the last,
  306.         } // if
  307.     } // for
  308.  
  309.     nMinHeight += m_cyBorder;                        //    Bottom border.
  310.  
  311.     return nMinHeight;
  312. }
  313.  
  314. void CMinSplitterWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
  315. {
  316.     //    Get minimum width and height of client area.
  317.     int nMinWidth    = GetMinClientWidth();
  318.     int nMinHeight    = GetMinClientHeight();
  319.  
  320.     //    Get the current window size.
  321.     CRect rcWindow;
  322.     GetWindowRect( rcWindow );
  323.     GetParent()->ScreenToClient( rcWindow );
  324.  
  325.     //    If trying to size too small...
  326.     if ( lpwndpos->cx < nMinWidth )
  327.     {
  328.         //    If dragging left border right...
  329.         if ( rcWindow.left < lpwndpos->x )
  330.         {
  331.             //    How much over are we?
  332.             int nOver = nMinWidth - lpwndpos->cx;
  333.             
  334.             //    Adjust left coord.
  335.             lpwndpos->x -= nOver;
  336.  
  337.         } // if
  338.  
  339.         //    Fix width.
  340.         lpwndpos->cx = nMinWidth;
  341.     } // if
  342.  
  343.     //    If trying to size too small...
  344.     if ( lpwndpos->cy < nMinHeight )
  345.     {
  346.         //    If dragging top border down...
  347.         if ( rcWindow.top < lpwndpos->y )
  348.         {
  349.             //    How much over are we?
  350.             int nOver = nMinHeight - lpwndpos->cy;
  351.             
  352.             //    Adjust left coord.
  353.             lpwndpos->y -= nOver;
  354.         } // if
  355.         
  356.         //    Fix height.
  357.         lpwndpos->cy = nMinHeight;
  358.     } // if
  359. }
  360.  
  361. // Generic routine:
  362. //  for X direction: pInfo = m_pColInfo, nMax = m_nMaxCols, nSize = cx
  363. //  for Y direction: pInfo = m_pRowInfo, nMax = m_nMaxRows, nSize = cy
  364. static void AFXAPI LayoutRowCol(CSplitterWnd::CRowColInfo* pInfoArray,
  365.     int nMax, int nSize, int nSizeSplitter)
  366. {
  367.     ASSERT(pInfoArray != NULL);
  368.     ASSERT(nMax > 0);
  369.     ASSERT(nSizeSplitter > 0);
  370.  
  371.     //    Save size for later on, because the second for loop modifies it.
  372.     int nSizeParm = nSize;
  373.  
  374.     CSplitterWnd::CRowColInfo* pInfo;
  375.     int i;
  376.  
  377.     if (nSize < 0)
  378.         nSize = 0;  // if really too small, layout as zero size
  379.  
  380.     // start with ideal sizes
  381.     for (i = 0, pInfo = pInfoArray; i < nMax-1; i++, pInfo++)
  382.     {
  383.         if (pInfo->nIdealSize < pInfo->nMinSize)
  384.             pInfo->nIdealSize = pInfo->nMinSize;      //    Can't be smaller than min.
  385.         pInfo->nCurSize = pInfo->nIdealSize;
  386.     }
  387.     pInfo->nCurSize = INT_MAX;  // last row/column takes the rest
  388.  
  389.     for (i = 0, pInfo = pInfoArray; i < nMax; i++, pInfo++)
  390.     {
  391.         ASSERT(nSize >= 0);
  392.         if ( nSize == 0 || nSize < pInfo->nMinSize && i != 0 )
  393.         {
  394.             //    OK, take what space we can for now.
  395.             pInfo->nCurSize = nSize;
  396.  
  397.             //    How much more space do I need?
  398.             int nNeed = pInfo->nMinSize - nSize;
  399.             ASSERT( nNeed > 0 );
  400.  
  401.             //    There must be a previous pane bigger than minimum size because 
  402.             //    of OnWindowPosChanging's restrictions.
  403.             bool    bDone    = false;
  404.             int        nCol    = nMax - 1;
  405.  
  406.             while ( ! bDone && nCol >= 0 )
  407.             {
  408.                 if ( nCol != i )
  409.                 {
  410.                     //    If we have found a pane with some size I can steal...
  411.                     if ( pInfoArray[ nCol ].nCurSize > pInfoArray[ nCol ].nMinSize )
  412.                     {
  413.                         //    How much can I steal?
  414.                         int nCanSteal = pInfoArray[ nCol ].nCurSize - pInfoArray[ nCol ].nMinSize;
  415.  
  416.                         //    If it is enough...
  417.                         if ( nCanSteal >= nNeed )
  418.                         {
  419.                             //    Yes, take what we need...
  420.                             pInfoArray[ nCol ].nCurSize -= nNeed;
  421.                             pInfoArray[ nCol ].nIdealSize -= nNeed;
  422.                             pInfo->nCurSize += nNeed;
  423.                             
  424.                             //    ...and exit the loop because all pane sizes are valid.
  425.                             bDone = true;
  426.                         }
  427.                         else if ( nCanSteal > 0 )
  428.                         {
  429.                             //    No, take what we can...
  430.                             pInfoArray[ nCol ].nCurSize -= nCanSteal;
  431.                             pInfoArray[ nCol ].nIdealSize -= nCanSteal;
  432.                             pInfo->nCurSize += nCanSteal;
  433.  
  434.                             //    ...update how much we still need.
  435.                             nNeed -= nCanSteal;
  436.                         } // if
  437.                     } // if
  438.                 } // if
  439.  
  440.                 //    Go back to previous pane.
  441.                 nCol--;
  442.             } // for
  443.  
  444.             nSize = 0;
  445.         }
  446.         else
  447.         {
  448.             // otherwise we can add the second pane
  449.             ASSERT(nSize > 0);
  450.             if (pInfo->nCurSize == 0)
  451.             {
  452.                 // too small to see
  453.                 if (i != 0)
  454.                     pInfo->nCurSize = 0;
  455.             }
  456.             else if (nSize < pInfo->nCurSize)
  457.             {
  458.                 // this row/col won't fit completely - make as small as possible
  459.                 pInfo->nCurSize = nSize;
  460.                 nSize = 0;
  461.             }
  462.             else
  463.             {
  464.                 // can fit everything
  465.                 nSize -= pInfo->nCurSize;
  466.             }
  467.         }
  468.  
  469.         // see if we should add a splitter
  470.         ASSERT(nSize >= 0);
  471.         if (i != nMax - 1)
  472.         {
  473.             // should have a splitter
  474.             if (nSize > nSizeSplitter)
  475.             {
  476.                 nSize -= nSizeSplitter; // leave room for splitter + border
  477.                 ASSERT(nSize > 0);
  478.             }
  479.             else
  480.             {
  481.                 // not enough room - add left over less splitter size
  482.                 ASSERT(afxData.cxBorder2 == afxData.cyBorder2);
  483.                 pInfo->nCurSize += nSize;
  484.                 if (pInfo->nCurSize > (nSizeSplitter - afxData.cxBorder2))
  485.                     pInfo->nCurSize -= (nSizeSplitter - afxData.cyBorder2);
  486.                 nSize = 0;
  487.             }
  488.         }
  489.     }
  490.     ASSERT(nSize == 0); // all space should be allocated
  491.  
  492.     //    Now ensure that none of the columns/rows are smaller than their minimum.
  493.     //    We can guarantee that all columns/row can be at least their minimum because
  494.     //    of our checks in OnWindowPosChanging.
  495.     for (i = 0, pInfo = pInfoArray; i < nMax; i++, pInfo++)
  496.     {
  497.         if ( pInfo->nCurSize < pInfo->nMinSize )
  498.         {
  499.             pInfo->nCurSize = pInfo->nMinSize;
  500.         } // if
  501.     } // for
  502. }
  503.  
  504. // repositions client area of specified window
  505. // assumes everything has WS_BORDER or is inset like it does
  506. //  (includes scroll bars)
  507. static void AFXAPI DeferClientPos(AFX_SIZEPARENTPARAMS* lpLayout,
  508.     CWnd* pWnd, int x, int y, int cx, int cy, BOOL bScrollBar)
  509. {
  510.     ASSERT(pWnd != NULL);
  511.     ASSERT(pWnd->m_hWnd != NULL);
  512.  
  513.     if (bScrollBar)
  514.     {
  515.         // if there is enough room, draw scroll bar without border
  516.         // if there is not enough room, set the WS_BORDER bit so that
  517.         //   we will at least get a proper border drawn
  518.         BOOL bNeedBorder = (cx <= CX_BORDER || cy <= CY_BORDER);
  519.         pWnd->ModifyStyle(bNeedBorder ? 0 : WS_BORDER,
  520.             bNeedBorder ? WS_BORDER : 0);
  521.     }
  522.     CRect rect(x, y, x+cx, y+cy);
  523.  
  524.     // adjust for border size (even if zero client size)
  525.     if (!afxData.bWin4)
  526.     {
  527.         if (bScrollBar)
  528.             rect.InflateRect(CX_BORDER, CY_BORDER);
  529.         else
  530.             pWnd->CalcWindowRect(&rect);
  531.     }
  532.  
  533.     // adjust for 3d border (splitter windows have implied border)
  534.     if ((pWnd->GetExStyle() & WS_EX_CLIENTEDGE) ||
  535.           pWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
  536.         rect.InflateRect(afxData.cxBorder2, afxData.cyBorder2);
  537.  
  538.     // first check if the new rectangle is the same as the current
  539.     CRect rectOld;
  540.     pWnd->GetWindowRect(rectOld);
  541.     pWnd->GetParent()->ScreenToClient(&rectOld);
  542.     if (rect != rectOld)
  543.         AfxRepositionWindow(lpLayout, pWnd->m_hWnd, rect);
  544. }
  545.  
  546. //==============================================================================
  547. //
  548. //    RecalcLayout
  549. //
  550. //    Remarks
  551. //    This function has been copied verbatim from winsplit.cpp purely because it
  552. //    calls LayoutRowCol, which for some reason the MFC developers decided to make
  553. //    a non-member function, so I can't override it.
  554. //
  555. //==============================================================================
  556. void CMinSplitterWnd::RecalcLayout()
  557. {
  558.     ASSERT_VALID(this);
  559.     ASSERT(m_nRows > 0 && m_nCols > 0); // must have at least one pane
  560.  
  561.     CRect rectClient;
  562.     GetClientRect(rectClient);
  563.     rectClient.InflateRect(-m_cxBorder, -m_cyBorder);
  564.  
  565.     CRect rectInside;
  566.     GetInsideRect(rectInside);
  567.  
  568.     // layout columns (restrict to possible sizes)
  569.     LayoutRowCol(m_pColInfo, m_nCols, rectInside.Width(), m_cxSplitterGap);
  570.     LayoutRowCol(m_pRowInfo, m_nRows, rectInside.Height(), m_cySplitterGap);
  571.  
  572.     // adjust the panes (and optionally scroll bars)
  573.  
  574.     // give the hint for the maximum number of HWNDs
  575.     AFX_SIZEPARENTPARAMS layout;
  576.     layout.hDWP = ::BeginDeferWindowPos((m_nCols + 1) * (m_nRows + 1) + 1);
  577.  
  578.     // size of scrollbars
  579.     int cx = (rectClient.right - rectInside.right) - afxData.bNotWin4;
  580.     int cy = (rectClient.bottom - rectInside.bottom) - afxData.bNotWin4;
  581.  
  582.     // reposition size box
  583.     if (m_bHasHScroll && m_bHasVScroll)
  584.     {
  585.         CWnd* pScrollBar = GetDlgItem(AFX_IDW_SIZE_BOX);
  586.         ASSERT(pScrollBar != NULL);
  587.  
  588.         // fix style if necessary
  589.         BOOL bSizingParent = (GetSizingParent() != NULL);
  590.         // modifyStyle returns TRUE if style changes
  591.         if (pScrollBar->ModifyStyle(SBS_SIZEGRIP|SBS_SIZEBOX,
  592.                 bSizingParent ? SBS_SIZEGRIP : SBS_SIZEBOX))
  593.             pScrollBar->Invalidate();
  594.         pScrollBar->EnableWindow(bSizingParent);
  595.  
  596.         // reposition the size box
  597.         DeferClientPos(&layout, pScrollBar,
  598.             rectInside.right + afxData.bNotWin4,
  599.             rectInside.bottom + afxData.bNotWin4, cx, cy, TRUE);
  600.     }
  601.  
  602.     // reposition scroll bars
  603.     if (m_bHasHScroll)
  604.     {
  605.         int cxSplitterBox = m_cxSplitter + afxData.bNotWin4;// split box bigger
  606.         int x = rectClient.left;
  607.         int y = rectInside.bottom + afxData.bNotWin4;
  608.         for (int col = 0; col < m_nCols; col++)
  609.         {
  610.             CWnd* pScrollBar = GetDlgItem(AFX_IDW_HSCROLL_FIRST + col);
  611.             ASSERT(pScrollBar != NULL);
  612.             int cx = m_pColInfo[col].nCurSize;
  613.             if (col == 0 && m_nCols < m_nMaxCols)
  614.                 x += cxSplitterBox, cx -= cxSplitterBox;
  615.             DeferClientPos(&layout, pScrollBar, x, y, cx, cy, TRUE);
  616.             x += cx + m_cxSplitterGap;
  617.         }
  618.     }
  619.  
  620.     if (m_bHasVScroll)
  621.     {
  622.         int cySplitterBox = m_cySplitter + afxData.bNotWin4;// split box bigger
  623.         int x = rectInside.right + afxData.bNotWin4;
  624.         int y = rectClient.top;
  625.         for (int row = 0; row < m_nRows; row++)
  626.         {
  627.             CWnd* pScrollBar = GetDlgItem(AFX_IDW_VSCROLL_FIRST + row);
  628.             ASSERT(pScrollBar != NULL);
  629.             int cy = m_pRowInfo[row].nCurSize;
  630.             if (row == 0 && m_nRows < m_nMaxRows)
  631.                 y += cySplitterBox, cy -= cySplitterBox;
  632.             DeferClientPos(&layout, pScrollBar, x, y, cx, cy, TRUE);
  633.             y += cy + m_cySplitterGap;
  634.         }
  635.     }
  636.  
  637.     //BLOCK: Reposition all the panes
  638.     {
  639.         int x = rectClient.left;
  640.         for (int col = 0; col < m_nCols; col++)
  641.         {
  642.             int cx = m_pColInfo[col].nCurSize;
  643.             int y = rectClient.top;
  644.             for (int row = 0; row < m_nRows; row++)
  645.             {
  646.                 int cy = m_pRowInfo[row].nCurSize;
  647.                 CWnd* pWnd = GetPane(row, col);
  648.                 DeferClientPos(&layout, pWnd, x, y, cx, cy, FALSE);
  649.                 y += cy + m_cySplitterGap;
  650.             }
  651.             x += cx + m_cxSplitterGap;
  652.         }
  653.     }
  654.  
  655.     // move and resize all the windows at once!
  656.     if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  657.         TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
  658.  
  659.     // invalidate all the splitter bars (with NULL pDC)
  660.     DrawAllSplitBars(NULL, rectInside.right, rectInside.bottom);
  661. }
  662.  
  663.