home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / DOCKCONT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  19.0 KB  |  716 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. #ifdef _MAC
  13. #include <macname1.h>
  14. #include <Types.h>
  15. #include <QuickDraw.h>
  16. #include <Events.h>
  17. #include <Menus.h>
  18. #include <macname2.h>
  19. #endif
  20.  
  21. #ifdef AFX_CORE3_SEG
  22. #pragma code_seg(AFX_CORE3_SEG)
  23. #endif
  24.  
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. #define new DEBUG_NEW
  31.  
  32. #define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
  33. #define VERTF(dw) (dw & CBRS_ORIENT_VERT)
  34.  
  35. static void AdjustRectangle(CRect& rect, CPoint pt)
  36. {
  37.     int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  38.                     (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  39.     int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  40.                     (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  41.     rect.OffsetRect(nXOffset, nYOffset);
  42. }
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CDockContext
  46.  
  47. CDockContext::CDockContext(CControlBar* pBar)
  48. {
  49.     ASSERT(pBar != NULL);
  50.     ASSERT(pBar->m_pDockSite != NULL);
  51.  
  52.     m_pBar = pBar;
  53.     m_pDockSite = pBar->m_pDockSite;
  54.  
  55.     m_uMRUDockID = 0;
  56.     m_rectMRUDockPos.left = 0;
  57.     m_rectMRUDockPos.top = 0;
  58.     if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
  59.         m_dwMRUFloatStyle = pBar->m_dwStyle & (CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC);
  60.     else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
  61.         m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  62.     else
  63.         m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  64.     m_ptMRUFloatPos.x = CW_USEDEFAULT;
  65.  
  66.     ASSERT(m_pDockSite->IsFrameWnd());
  67.     m_pDC = NULL;
  68. }
  69.  
  70. CDockContext::~CDockContext()
  71. {
  72.     ASSERT(m_pBar != NULL);
  73.     if (m_pBar->m_pDockBar != NULL)
  74.         m_pBar->m_pDockBar->RemoveControlBar(m_pBar, -1, FALSE);
  75. }
  76.  
  77. /////////////////////////////////////////////////////////////////////////////
  78. // CDockContext Drag Operations
  79.  
  80. void CDockContext::StartDrag(CPoint pt)
  81. {
  82.     ASSERT_VALID(m_pBar);
  83.     m_bDragging = TRUE;
  84.  
  85.     InitLoop();
  86.  
  87.     if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
  88.     {
  89.         // get true bar size (including borders)
  90.         CRect rect;
  91.         m_pBar->GetWindowRect(rect);
  92.         m_ptLast = pt;
  93.         CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
  94.         CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
  95.         CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  96.  
  97.         m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  98.         m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  99.  
  100.         // calculate frame dragging rectangle
  101.         m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
  102.         m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat);
  103.  
  104. #ifdef _MAC
  105.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
  106.             WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
  107.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert,
  108.             WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
  109. #else
  110.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  111.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  112. #endif
  113.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  114.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  115.     }
  116.     else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED)
  117.     {
  118.         // get true bar size (including borders)
  119.         CRect rect;
  120.         m_pBar->GetWindowRect(rect);
  121.         m_ptLast = pt;
  122.         CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK);
  123.         CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK);
  124.  
  125.         // calculate frame dragging rectangle
  126.         m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  127.         m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  128.  
  129.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  130.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  131.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  132.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  133.     }
  134.     else
  135.     {
  136.         // get true bar size (including borders)
  137.         CRect rect;
  138.         m_pBar->GetWindowRect(rect);
  139.         m_ptLast = pt;
  140.         BOOL bHorz = HORZF(m_dwStyle);
  141.         DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK;
  142.         CSize size = m_pBar->CalcDynamicLayout(-1, dwMode);
  143.  
  144.         // calculate inverted dragging rect
  145.         if (bHorz)
  146.         {
  147.             m_rectDragHorz = rect;
  148.             m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size);
  149.         }
  150.         else // vertical orientation
  151.         {
  152.             m_rectDragVert = rect;
  153.             m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size);
  154.         }
  155.  
  156.         // calculate frame dragging rectangle
  157.         m_rectFrameDragHorz = m_rectDragHorz;
  158.         m_rectFrameDragVert = m_rectDragVert;
  159.  
  160.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  161.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  162.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  163.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  164.     }
  165.  
  166.     // adjust rectangles so that point is inside
  167.     AdjustRectangle(m_rectDragHorz, pt);
  168.     AdjustRectangle(m_rectDragVert, pt);
  169.     AdjustRectangle(m_rectFrameDragHorz, pt);
  170.     AdjustRectangle(m_rectFrameDragVert, pt);
  171.  
  172.     // initialize tracking state and enter tracking loop
  173.     m_dwOverDockStyle = CanDock();
  174.     Move(pt);   // call it here to handle special keys
  175.     Track();
  176. }
  177.  
  178. void CDockContext::Move(CPoint pt)
  179. {
  180.     CPoint ptOffset = pt - m_ptLast;
  181.  
  182. #ifdef _MAC
  183.     // prevent dragging the floating window completely under the menu bar
  184.     GDHandle hgd = _AfxFindDevice(pt.x, pt.y);
  185.     if (hgd == NULL || hgd == GetMainDevice() ||
  186.             TestDeviceAttribute(hgd, hasAuxMenuBar))
  187.     {
  188.         CRect rect;
  189.         if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
  190.             rect = m_rectFrameDragHorz;
  191.         else
  192.             rect = m_rectFrameDragVert;
  193.  
  194.         // determine our new position
  195.         rect.OffsetRect(ptOffset);
  196.  
  197.         // keep us on the screen if we were getting too close to the menu bar
  198.         int yMBarBottom = (*hgd)->gdRect.top + GetMBarHeight() + 4;
  199.         if (rect.bottom < yMBarBottom)
  200.         {
  201.             pt.y += yMBarBottom - rect.bottom;
  202.             ptOffset.y += yMBarBottom - rect.bottom;
  203.         }
  204.     }
  205. #endif
  206.  
  207.     // offset all drag rects to new position
  208.     m_rectDragHorz.OffsetRect(ptOffset);
  209.     m_rectFrameDragHorz.OffsetRect(ptOffset);
  210.     m_rectDragVert.OffsetRect(ptOffset);
  211.     m_rectFrameDragVert.OffsetRect(ptOffset);
  212.     m_ptLast = pt;
  213.  
  214.     // if control key is down don't dock
  215.     m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
  216.  
  217.     // update feedback
  218.     DrawFocusRect();
  219. }
  220.  
  221. void CDockContext::OnKey(int nChar, BOOL bDown)
  222. {
  223.     if (nChar == VK_CONTROL)
  224.         UpdateState(&m_bForceFrame, bDown);
  225.     if (nChar == VK_SHIFT)
  226.         UpdateState(&m_bFlip, bDown);
  227. }
  228.  
  229. void CDockContext::EndDrag()
  230. {
  231.     CancelLoop();
  232.  
  233.     if (m_dwOverDockStyle != 0)
  234.     {
  235.         CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle);
  236.         ASSERT(pDockBar != NULL);
  237.  
  238.         CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ?
  239.             m_rectDragVert : m_rectDragHorz;
  240.  
  241.         UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd);
  242.         if (uID >= AFX_IDW_DOCKBAR_TOP &&
  243.             uID <= AFX_IDW_DOCKBAR_BOTTOM)
  244.         {
  245.             m_uMRUDockID = uID;
  246.             m_rectMRUDockPos = rect;
  247.             pDockBar->ScreenToClient(&m_rectMRUDockPos);
  248.         }
  249.  
  250.         // dock it at the specified position, RecalcLayout will snap
  251.         m_pDockSite->DockControlBar(m_pBar, pDockBar, &rect);
  252.         m_pDockSite->RecalcLayout();
  253.     }
  254.     else if ((m_dwStyle & CBRS_SIZE_DYNAMIC) || (HORZF(m_dwStyle) && !m_bFlip) ||
  255.             (VERTF(m_dwStyle) && m_bFlip))
  256.     {
  257.         m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  258.         m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft();
  259.         m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  260.     }
  261.     else // vertical float
  262.     {
  263.         m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  264.         m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft();
  265.         m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  266.     }
  267. }
  268.  
  269. /////////////////////////////////////////////////////////////////////////////
  270. // CDockContext Resize Operations
  271.  
  272. #define m_rectRequestedSize     m_rectDragHorz
  273. #define m_rectActualSize        m_rectDragVert
  274. #define m_rectActualFrameSize   m_rectFrameDragHorz
  275. #define m_rectFrameBorders      m_rectFrameDragVert
  276.  
  277. void CDockContext::StartResize(int nHitTest, CPoint pt)
  278. {
  279.     ASSERT_VALID(m_pBar);
  280.     ASSERT(m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC);
  281.     m_bDragging = FALSE;
  282.  
  283.     InitLoop();
  284.  
  285.     // get true bar size (including borders)
  286.     CRect rect;
  287.     m_pBar->GetWindowRect(rect);
  288.     m_ptLast = pt;
  289.     m_nHitTest = nHitTest;
  290.  
  291.     CSize size = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  292.     m_rectRequestedSize = CRect(rect.TopLeft(), size);
  293.     m_rectActualSize = CRect(rect.TopLeft(), size);
  294.     m_rectActualFrameSize = CRect(rect.TopLeft(), size);
  295.  
  296.     // calculate frame rectangle
  297. #ifdef _MAC
  298.     CMiniFrameWnd::CalcBorders(&m_rectActualFrameSize,
  299.         WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
  300. #else
  301.     CMiniFrameWnd::CalcBorders(&m_rectActualFrameSize);
  302. #endif
  303.     m_rectActualFrameSize.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  304.  
  305.     m_rectFrameBorders = CRect(CPoint(0,0),
  306.         m_rectActualFrameSize.Size() - m_rectActualSize.Size());
  307.  
  308.     // initialize tracking state and enter tracking loop
  309.     m_dwOverDockStyle = 0;
  310.     Stretch(pt);   // call it here to handle special keys
  311.     Track();
  312. }
  313.  
  314. void CDockContext::Stretch(CPoint pt)
  315. {
  316.     CPoint ptOffset = pt - m_ptLast;
  317.  
  318.     // offset all drag rects to new position
  319.     int nLength = 0;
  320.     DWORD dwMode = LM_HORZ;
  321.     if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT)
  322.     {
  323.         if (m_nHitTest == HTLEFT)
  324.             m_rectRequestedSize.left += ptOffset.x;
  325.         else
  326.             m_rectRequestedSize.right += ptOffset.x;
  327.         nLength = m_rectRequestedSize.Width();
  328.     }
  329.     else
  330.     {
  331.         dwMode |= LM_LENGTHY;
  332.         if (m_nHitTest == HTTOP)
  333.             m_rectRequestedSize.top += ptOffset.y;
  334.         else
  335.             m_rectRequestedSize.bottom += ptOffset.y;
  336.         nLength = m_rectRequestedSize.Height();
  337.     }
  338.     nLength = (nLength >= 0) ? nLength : 0;
  339.  
  340.     CSize size = m_pBar->CalcDynamicLayout(nLength, dwMode);
  341.     if (m_nHitTest == HTLEFT || m_nHitTest == HTTOP)
  342.     {
  343.         m_rectActualSize.left = m_rectActualSize.right - size.cx;
  344.         m_rectActualSize.top = m_rectActualSize.bottom - size.cy;
  345.         m_rectActualFrameSize.left = m_rectActualFrameSize.right -
  346.             (size.cx + m_rectFrameBorders.Width());
  347.         m_rectActualFrameSize.top = m_rectActualFrameSize.bottom -
  348.             (size.cy + m_rectFrameBorders.Height());
  349.     }
  350.     else
  351.     {
  352.         m_rectActualSize.right = m_rectActualSize.left + size.cx;
  353.         m_rectActualSize.bottom = m_rectActualSize.top + size.cy;
  354.         m_rectActualFrameSize.right = m_rectActualFrameSize.left +
  355.             (size.cx + m_rectFrameBorders.Width());
  356.         m_rectActualFrameSize.bottom = m_rectActualFrameSize.top +
  357.             (size.cy + m_rectFrameBorders.Height());
  358.     }
  359.     m_ptLast = pt;
  360.  
  361.     // update feedback
  362.     DrawFocusRect();
  363. }
  364.  
  365. void CDockContext::EndResize()
  366. {
  367.     CancelLoop();
  368.  
  369.     m_pBar->CalcDynamicLayout(m_rectActualSize.Width(), LM_HORZ | LM_COMMIT);
  370.     m_pDockSite->FloatControlBar(m_pBar, m_rectActualFrameSize.TopLeft(),
  371.         CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI) | CBRS_SIZE_DYNAMIC);
  372. }
  373.  
  374. /////////////////////////////////////////////////////////////////////////////
  375. // CDockContext Double Click Operations
  376.  
  377. void CDockContext::ToggleDocking()
  378. {
  379.     if (m_pBar->IsFloating())
  380.     {
  381.         // Dock it only if is allowed to be docked
  382.         if (m_pBar->m_dwDockStyle & CBRS_ALIGN_ANY)
  383.         {
  384.             ASSERT((m_uMRUDockID >= AFX_IDW_DOCKBAR_TOP &&
  385.                 m_uMRUDockID <= AFX_IDW_DOCKBAR_BOTTOM) ||
  386.                 m_uMRUDockID == 0);
  387.  
  388.             CRect rect = m_rectMRUDockPos;
  389.             CDockBar* pDockBar = NULL;
  390.             if (m_uMRUDockID != 0)
  391.             {
  392.                 pDockBar = (CDockBar*)m_pDockSite->GetControlBar(m_uMRUDockID);
  393.                 pDockBar->ClientToScreen(&rect);
  394.             }
  395.  
  396.             // dock it at the specified position, RecalcLayout will snap
  397.             m_pDockSite->ReDockControlBar(m_pBar, pDockBar, &rect);
  398.             m_pDockSite->RecalcLayout();
  399.         }
  400.     }
  401.     else
  402.     {
  403.         CPoint ptFloat = m_ptMRUFloatPos;
  404.         if (ptFloat.x < 0 || ptFloat.y < 0)
  405.         {
  406.             ptFloat = m_rectMRUDockPos.TopLeft();
  407.             m_pBar->GetParent()->ClientToScreen(&ptFloat);
  408.         }
  409.         m_pDockSite->FloatControlBar(m_pBar, ptFloat, m_dwMRUFloatStyle);
  410.     }
  411. }
  412.  
  413. /////////////////////////////////////////////////////////////////////////////
  414. // CDockContext Operations
  415.  
  416. void CDockContext::InitLoop()
  417. {
  418.     // handle pending WM_PAINT messages
  419.     MSG msg;
  420.     while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  421.     {
  422.         if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  423.             return;
  424.         DispatchMessage(&msg);
  425.     }
  426.  
  427.     // get styles from bar
  428.     m_dwDockStyle = m_pBar->m_dwDockStyle;
  429.     m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY;
  430.     ASSERT(m_dwStyle != 0);
  431.  
  432.     // initialize state
  433.     m_rectLast.SetRectEmpty();
  434.     m_sizeLast.cx = m_sizeLast.cy = 0;
  435.     m_bForceFrame = m_bFlip = m_bDitherLast = FALSE;
  436.  
  437.     // lock window update while dragging
  438.     ASSERT(m_pDC == NULL);
  439.     CWnd* pWnd = CWnd::GetDesktopWindow();
  440. #ifndef _MAC
  441.     if (pWnd->LockWindowUpdate())
  442.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  443.     else
  444. #endif
  445.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
  446.     ASSERT(m_pDC != NULL);
  447. }
  448.  
  449. void CDockContext::CancelLoop()
  450. {
  451.     DrawFocusRect(TRUE);    // gets rid of focus rect
  452.     ReleaseCapture();
  453.  
  454.     CWnd* pWnd = CWnd::GetDesktopWindow();
  455. #ifndef _MAC
  456.     pWnd->UnlockWindowUpdate();
  457. #endif
  458.     if (m_pDC != NULL)
  459.     {
  460.         pWnd->ReleaseDC(m_pDC);
  461.         m_pDC = NULL;
  462.     }
  463. }
  464.  
  465. /////////////////////////////////////////////////////////////////////////////
  466. // Implementation
  467.  
  468. void CDockContext::DrawFocusRect(BOOL bRemoveRect)
  469. {
  470.     ASSERT(m_pDC != NULL);
  471.  
  472.     // default to thin frame
  473.     CSize size(CX_BORDER, CY_BORDER);
  474.  
  475.     // determine new rect and size
  476.     CRect rect;
  477.     CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
  478.     CBrush* pDitherBrush = CDC::GetHalftoneBrush();
  479.     CBrush* pBrush = pWhiteBrush;
  480.  
  481.     if (HORZF(m_dwOverDockStyle))
  482.         rect = m_rectDragHorz;
  483.     else if (VERTF(m_dwOverDockStyle))
  484.         rect = m_rectDragVert;
  485.     else
  486.     {
  487. #ifndef _MAC
  488.         // use thick frame instead
  489.         size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER;
  490.         size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER;
  491. #endif
  492.         if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
  493.             rect = m_rectFrameDragHorz;
  494.         else
  495.             rect = m_rectFrameDragVert;
  496.         pBrush = pDitherBrush;
  497.     }
  498.     if (bRemoveRect)
  499.         size.cx = size.cy = 0;
  500.  
  501.     if (afxData.bWin4 &&
  502.         (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle)))
  503.     {
  504.         // looks better one pixel in (makes the bar look pushed down)
  505.         rect.InflateRect(-CX_BORDER, -CY_BORDER);
  506.     }
  507.  
  508.     // draw it and remember last size
  509.     m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
  510.         pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
  511.     m_rectLast = rect;
  512.     m_sizeLast = size;
  513.     m_bDitherLast = (pBrush == pDitherBrush);
  514. }
  515.  
  516. void CDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue)
  517. {
  518.     if (*pFlag != bNewValue)
  519.     {
  520.         *pFlag = bNewValue;
  521.         m_bFlip = (HORZF(m_dwDockStyle) && VERTF(m_dwDockStyle) && m_bFlip); // shift key
  522.         m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock();
  523.         DrawFocusRect();
  524.     }
  525. }
  526.  
  527. DWORD CDockContext::CanDock()
  528. {
  529.     BOOL bStyleHorz;
  530.     DWORD dwDock = 0; // Dock Canidate
  531.     DWORD dwCurr = 0; // Current Orientation
  532.  
  533.     // let's check for something in our current orientation first
  534.     // then if the shift key is not forcing our orientation then
  535.     // check for horizontal or vertical orientations as long
  536.     // as we are close enough
  537.     ASSERT(m_dwStyle != 0);
  538.  
  539.     bStyleHorz = HORZF(m_dwStyle);
  540.     bStyleHorz = m_bFlip ? !bStyleHorz : bStyleHorz;
  541.  
  542.     if (bStyleHorz && HORZF(m_dwDockStyle))
  543.         dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  544.                                       m_dwDockStyle & ~CBRS_ORIENT_VERT);
  545.     else if (VERTF(m_dwDockStyle))
  546.         dwDock = m_pDockSite->CanDock(m_rectDragVert,
  547.                                       m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  548.  
  549.     if (!m_bFlip)
  550.     {
  551.         if (dwDock == 0 && HORZF(m_dwDockStyle))
  552.         {
  553.             dwCurr = m_pDockSite->CanDock(m_rectDragVert,
  554.                                           m_dwDockStyle & ~CBRS_ORIENT_VERT);
  555.             dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  556.                                           m_dwDockStyle & ~CBRS_ORIENT_VERT);
  557.             dwDock = (dwDock == dwCurr) ? dwDock : 0;
  558.         }
  559.         if (dwDock == 0 && VERTF(m_dwDockStyle))
  560.         {
  561.             dwCurr = m_pDockSite->CanDock(m_rectDragHorz,
  562.                                           m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  563.             dwDock = m_pDockSite->CanDock(m_rectDragVert,
  564.                                           m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  565.             dwDock = (dwDock == dwCurr) ? dwDock : 0;
  566.         }
  567.     }
  568.  
  569.     return dwDock;
  570. }
  571.  
  572. CDockBar* CDockContext::GetDockBar(DWORD dwOverDockStyle)
  573. {
  574.     DWORD dw = 0;
  575.     CDockBar* pBar;
  576.     if (HORZF(dwOverDockStyle))
  577.     {
  578.         dw = m_pDockSite->CanDock(m_rectDragHorz,
  579.             dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar);
  580.         ASSERT(dw != 0);
  581.         ASSERT(pBar != NULL);
  582.         return pBar;
  583.     }
  584.     if (VERTF(dwOverDockStyle))
  585.     {
  586.         dw = m_pDockSite->CanDock(m_rectDragVert,
  587.             dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar);
  588.         ASSERT(dw != 0);
  589.         ASSERT(pBar != NULL);
  590.         return pBar;
  591.     }
  592.     return NULL;
  593. }
  594.  
  595. BOOL CDockContext::Track()
  596. {
  597.     // don't handle if capture already set
  598.     if (::GetCapture() != NULL)
  599.         return FALSE;
  600.  
  601.     // set capture to the window which received this message
  602.     m_pBar->SetCapture();
  603.     ASSERT(m_pBar == CWnd::GetCapture());
  604.  
  605. #ifndef _MAC
  606.     // get messages until capture lost or cancelled/accepted
  607.     while (CWnd::GetCapture() == m_pBar)
  608.     {
  609.         MSG msg;
  610.         if (!::GetMessage(&msg, NULL, 0, 0))
  611.         {
  612.             AfxPostQuitMessage(msg.wParam);
  613.             break;
  614.         }
  615.  
  616.         switch (msg.message)
  617.         {
  618.         case WM_LBUTTONUP:
  619.             if (m_bDragging)
  620.                 EndDrag();
  621.             else
  622.                 EndResize();
  623.             return TRUE;
  624.         case WM_MOUSEMOVE:
  625.             if (m_bDragging)
  626.                 Move(msg.pt);
  627.             else
  628.                 Stretch(msg.pt);
  629.             break;
  630.         case WM_KEYUP:
  631.             if (m_bDragging)
  632.                 OnKey((int)msg.wParam, FALSE);
  633.             break;
  634.         case WM_KEYDOWN:
  635.             if (m_bDragging)
  636.                 OnKey((int)msg.wParam, TRUE);
  637.             if (msg.wParam == VK_ESCAPE)
  638.             {
  639.                 CancelLoop();
  640.                 return FALSE;
  641.             }
  642.             break;
  643.         case WM_RBUTTONDOWN:
  644.             CancelLoop();
  645.             return FALSE;
  646.  
  647.         // just dispatch rest of the messages
  648.         default:
  649.             DispatchMessage(&msg);
  650.             break;
  651.         }
  652.     }
  653. #else
  654.     Point   ptCur = {0};
  655.  
  656.     // get messages until capture lost or cancelled/accepted
  657.     while (CWnd::GetCapture() == m_pBar)
  658.     {
  659.         EventRecord     er;
  660.  
  661.         if (OSEventAvail(everyEvent, &er))
  662.         {
  663.             GetNextEvent(everyEvent, &er);
  664.             switch (er.what)
  665.             {
  666.             case mouseUp:
  667.                 if (m_bDragging)
  668.                     EndDrag();
  669.                 else
  670.                     EndResize();
  671.                 return TRUE;
  672.  
  673.             case keyDown:
  674.             case keyUp:
  675.             case autoKey:
  676.             case app2Evt:
  677.             {
  678.                 MSG     msg;
  679.  
  680.                 if (WrapEvent(&er, &msg, PM_REMOVE))
  681.                 {
  682.                     if (m_bDragging)
  683.                         OnKey((int)msg.wParam, msg.message == WM_KEYDOWN);
  684.                     if (msg.message == WM_KEYUP && msg.wParam == VK_ESCAPE)
  685.                     {
  686.                         CancelLoop();
  687.                         return FALSE;
  688.                     }
  689.                 }
  690.                 break;
  691.             }
  692.  
  693.             default:
  694.                 break;
  695.             }
  696.         }
  697.         else
  698.         {
  699.             if (!EqualPt(er.where, ptCur))
  700.             {
  701.                 POINT pt = {er.where.h, er.where.v};
  702.                 if (m_bDragging)
  703.                     Move(pt);
  704.                 else
  705.                     Stretch(pt);
  706.             }
  707.         }
  708.     }
  709. #endif
  710.     CancelLoop();
  711.  
  712.     return FALSE;
  713. }
  714.  
  715. /////////////////////////////////////////////////////////////////////////////
  716.