home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / dockcont.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-16  |  17.8 KB  |  642 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. #define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
  25. #define VERTF(dw) (dw & CBRS_ORIENT_VERT)
  26.  
  27. AFX_STATIC void AFXAPI _AfxAdjustRectangle(CRect& rect, CPoint pt)
  28. {
  29.     int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  30.                     (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  31.     int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  32.                     (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  33.     rect.OffsetRect(nXOffset, nYOffset);
  34. }
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CDockContext
  38.  
  39. CDockContext::CDockContext(CControlBar* pBar)
  40. {
  41.     ASSERT(pBar != NULL);
  42.     ASSERT(pBar->m_pDockSite != NULL);
  43.  
  44.     m_pBar = pBar;
  45.     m_pDockSite = pBar->m_pDockSite;
  46.  
  47.     m_uMRUDockID = 0;
  48.     m_rectMRUDockPos.left = 0;
  49.     m_rectMRUDockPos.top = 0;
  50.     if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
  51.         m_dwMRUFloatStyle = pBar->m_dwStyle & (CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC);
  52.     else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
  53.         m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  54.     else
  55.         m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  56.     m_ptMRUFloatPos.x = CW_USEDEFAULT;
  57.  
  58.     ASSERT(m_pDockSite->IsFrameWnd());
  59.     m_pDC = NULL;
  60. }
  61.  
  62. CDockContext::~CDockContext()
  63. {
  64.     ASSERT(m_pBar != NULL);
  65.     if (m_pBar->m_pDockBar != NULL)
  66.         m_pBar->m_pDockBar->RemoveControlBar(m_pBar, -1, FALSE);
  67. }
  68.  
  69. /////////////////////////////////////////////////////////////////////////////
  70. // CDockContext Drag Operations
  71.  
  72. void CDockContext::StartDrag(CPoint pt)
  73. {
  74.     ASSERT_VALID(m_pBar);
  75.     m_bDragging = TRUE;
  76.  
  77.     InitLoop();
  78.  
  79.     // GetWindowRect returns screen coordinates(not mirrored),
  80.     // so if the desktop is mirrored then turn off mirroring
  81.     // for the desktop dc so that we get correct focus rect drawn.
  82.     // This layout change should be remembered, just in case ...
  83.  
  84.     if (m_pDC->GetLayout() & LAYOUT_RTL)
  85.         m_pDC->SetLayout(LAYOUT_LTR);
  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.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  105.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  106.  
  107.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  108.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  109.     }
  110.     else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED)
  111.     {
  112.         // get true bar size (including borders)
  113.         CRect rect;
  114.         m_pBar->GetWindowRect(rect);
  115.         m_ptLast = pt;
  116.         CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK);
  117.         CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK);
  118.  
  119.         // calculate frame dragging rectangle
  120.         m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  121.         m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  122.  
  123.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  124.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  125.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  126.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  127.     }
  128.     else
  129.     {
  130.         // get true bar size (including borders)
  131.         CRect rect;
  132.         m_pBar->GetWindowRect(rect);
  133.         m_ptLast = pt;
  134.         BOOL bHorz = HORZF(m_dwStyle);
  135.         DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK;
  136.         CSize size = m_pBar->CalcDynamicLayout(-1, dwMode);
  137.  
  138.         // calculate inverted dragging rect
  139.         if (bHorz)
  140.         {
  141.             m_rectDragHorz = rect;
  142.             m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size);
  143.         }
  144.         else // vertical orientation
  145.         {
  146.             m_rectDragVert = rect;
  147.             m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size);
  148.         }
  149.  
  150.         // calculate frame dragging rectangle
  151.         m_rectFrameDragHorz = m_rectDragHorz;
  152.         m_rectFrameDragVert = m_rectDragVert;
  153.  
  154.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  155.         CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  156.         m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  157.         m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  158.     }
  159.  
  160.     // adjust rectangles so that point is inside
  161.     _AfxAdjustRectangle(m_rectDragHorz, pt);
  162.     _AfxAdjustRectangle(m_rectDragVert, pt);
  163.     _AfxAdjustRectangle(m_rectFrameDragHorz, pt);
  164.     _AfxAdjustRectangle(m_rectFrameDragVert, pt);
  165.  
  166.     // initialize tracking state and enter tracking loop
  167.     m_dwOverDockStyle = CanDock();
  168.     Move(pt);   // call it here to handle special keys
  169.     Track();
  170. }
  171.  
  172. void CDockContext::Move(CPoint pt)
  173. {
  174.     CPoint ptOffset = pt - m_ptLast;
  175.  
  176.     // offset all drag rects to new position
  177.     m_rectDragHorz.OffsetRect(ptOffset);
  178.     m_rectFrameDragHorz.OffsetRect(ptOffset);
  179.     m_rectDragVert.OffsetRect(ptOffset);
  180.     m_rectFrameDragVert.OffsetRect(ptOffset);
  181.     m_ptLast = pt;
  182.  
  183.     // if control key is down don't dock
  184.     m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
  185.  
  186.     // update feedback
  187.     DrawFocusRect();
  188. }
  189.  
  190. void CDockContext::OnKey(int nChar, BOOL bDown)
  191. {
  192.     if (nChar == VK_CONTROL)
  193.         UpdateState(&m_bForceFrame, bDown);
  194.     if (nChar == VK_SHIFT)
  195.         UpdateState(&m_bFlip, bDown);
  196. }
  197.  
  198. void CDockContext::EndDrag()
  199. {
  200.     CancelLoop();
  201.  
  202.     if (m_dwOverDockStyle != 0)
  203.     {
  204.         CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle);
  205.         ASSERT(pDockBar != NULL);
  206.  
  207.         CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ?
  208.             m_rectDragVert : m_rectDragHorz;
  209.  
  210.         UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd);
  211.         if (uID >= AFX_IDW_DOCKBAR_TOP &&
  212.             uID <= AFX_IDW_DOCKBAR_BOTTOM)
  213.         {
  214.             m_uMRUDockID = uID;
  215.             m_rectMRUDockPos = rect;
  216.             pDockBar->ScreenToClient(&m_rectMRUDockPos);
  217.         }
  218.  
  219.         // dock it at the specified position, RecalcLayout will snap
  220.         m_pDockSite->DockControlBar(m_pBar, pDockBar, &rect);
  221.         m_pDockSite->RecalcLayout();
  222.     }
  223.     else if ((m_dwStyle & CBRS_SIZE_DYNAMIC) || (HORZF(m_dwStyle) && !m_bFlip) ||
  224.             (VERTF(m_dwStyle) && m_bFlip))
  225.     {
  226.         m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  227.         m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft();
  228.         m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  229.     }
  230.     else // vertical float
  231.     {
  232.         m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  233.         m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft();
  234.         m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  235.     }
  236. }
  237.  
  238. /////////////////////////////////////////////////////////////////////////////
  239. // CDockContext Resize Operations
  240.  
  241. #define m_rectRequestedSize     m_rectDragHorz
  242. #define m_rectActualSize        m_rectDragVert
  243. #define m_rectActualFrameSize   m_rectFrameDragHorz
  244. #define m_rectFrameBorders      m_rectFrameDragVert
  245.  
  246. void CDockContext::StartResize(int nHitTest, CPoint pt)
  247. {
  248.     ASSERT_VALID(m_pBar);
  249.     ASSERT(m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC);
  250.     m_bDragging = FALSE;
  251.  
  252.     InitLoop();
  253.  
  254.     // GetWindowRect returns screen coordinates(not mirrored)
  255.     // So if the desktop is mirrored then turn off mirroring
  256.     // for the desktop dc so that we draw correct focus rect
  257.  
  258.     if (m_pDC->GetLayout() & LAYOUT_RTL)
  259.         m_pDC->SetLayout(LAYOUT_LTR);
  260.  
  261.     // get true bar size (including borders)
  262.     CRect rect;
  263.     m_pBar->GetWindowRect(rect);
  264.     m_ptLast = pt;
  265.     m_nHitTest = nHitTest;
  266.  
  267.     CSize size = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  268.     m_rectRequestedSize = CRect(rect.TopLeft(), size);
  269.     m_rectActualSize = CRect(rect.TopLeft(), size);
  270.     m_rectActualFrameSize = CRect(rect.TopLeft(), size);
  271.  
  272.     // calculate frame rectangle
  273.     CMiniFrameWnd::CalcBorders(&m_rectActualFrameSize);
  274.     m_rectActualFrameSize.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  275.  
  276.     m_rectFrameBorders = CRect(CPoint(0,0),
  277.         m_rectActualFrameSize.Size() - m_rectActualSize.Size());
  278.  
  279.     // initialize tracking state and enter tracking loop
  280.     m_dwOverDockStyle = 0;
  281.     Stretch(pt);   // call it here to handle special keys
  282.     Track();
  283. }
  284.  
  285. void CDockContext::Stretch(CPoint pt)
  286. {
  287.     CPoint ptOffset = pt - m_ptLast;
  288.  
  289.     // offset all drag rects to new position
  290.     int nLength = 0;
  291.     DWORD dwMode = LM_HORZ;
  292.     if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT)
  293.     {
  294.         if (m_nHitTest == HTLEFT)
  295.             m_rectRequestedSize.left += ptOffset.x;
  296.         else
  297.             m_rectRequestedSize.right += ptOffset.x;
  298.         nLength = m_rectRequestedSize.Width();
  299.     }
  300.     else
  301.     {
  302.         dwMode |= LM_LENGTHY;
  303.         if (m_nHitTest == HTTOP)
  304.             m_rectRequestedSize.top += ptOffset.y;
  305.         else
  306.             m_rectRequestedSize.bottom += ptOffset.y;
  307.         nLength = m_rectRequestedSize.Height();
  308.     }
  309.     nLength = (nLength >= 0) ? nLength : 0;
  310.  
  311.     CSize size = m_pBar->CalcDynamicLayout(nLength, dwMode);
  312.  
  313.     CRect rectDesk;
  314.     HWND hWndDesk = ::GetDesktopWindow();
  315.     ::GetWindowRect(hWndDesk, &rectDesk);
  316.     CRect rectTemp = m_rectActualFrameSize;
  317.  
  318.     if (m_nHitTest == HTLEFT || m_nHitTest == HTTOP)
  319.     {
  320.         rectTemp.left = rectTemp.right -
  321.             (size.cx + m_rectFrameBorders.Width());
  322.         rectTemp.top = rectTemp.bottom -
  323.             (size.cy + m_rectFrameBorders.Height());
  324.         CRect rect;
  325.         if (rect.IntersectRect(rectDesk, rectTemp))
  326.         {
  327.             m_rectActualSize.left = m_rectActualSize.right - size.cx;
  328.             m_rectActualSize.top = m_rectActualSize.bottom - size.cy;
  329.             m_rectActualFrameSize.left = rectTemp.left;
  330.             m_rectActualFrameSize.top = rectTemp.top;
  331.         }
  332.     }
  333.     else
  334.     {
  335.         rectTemp.right = rectTemp.left +
  336.             (size.cx + m_rectFrameBorders.Width());
  337.         rectTemp.bottom = rectTemp.top +
  338.             (size.cy + m_rectFrameBorders.Height());
  339.         CRect rect;
  340.         if (rect.IntersectRect(rectDesk, rectTemp))
  341.         {
  342.             m_rectActualSize.right = m_rectActualSize.left + size.cx;
  343.             m_rectActualSize.bottom = m_rectActualSize.top + size.cy;
  344.             m_rectActualFrameSize.right = rectTemp.right;
  345.             m_rectActualFrameSize.bottom = rectTemp.bottom;
  346.         }
  347.     }
  348.     m_ptLast = pt;
  349.  
  350.     // update feedback
  351.     DrawFocusRect();
  352. }
  353.  
  354. void CDockContext::EndResize()
  355. {
  356.     CancelLoop();
  357.  
  358.     m_pBar->CalcDynamicLayout(m_rectActualSize.Width(), LM_HORZ | LM_COMMIT);
  359.     m_pDockSite->FloatControlBar(m_pBar, m_rectActualFrameSize.TopLeft(),
  360.         CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI) | CBRS_SIZE_DYNAMIC);
  361. }
  362.  
  363. /////////////////////////////////////////////////////////////////////////////
  364. // CDockContext Double Click Operations
  365.  
  366. void CDockContext::ToggleDocking()
  367. {
  368.     if (m_pBar->IsFloating())
  369.     {
  370.         // Dock it only if is allowed to be docked
  371.         if (m_pBar->m_dwDockStyle & CBRS_ALIGN_ANY)
  372.         {
  373.             ASSERT((m_uMRUDockID >= AFX_IDW_DOCKBAR_TOP &&
  374.                 m_uMRUDockID <= AFX_IDW_DOCKBAR_BOTTOM) ||
  375.                 m_uMRUDockID == 0);
  376.  
  377.             CRect rect = m_rectMRUDockPos;
  378.             CDockBar* pDockBar = NULL;
  379.             if (m_uMRUDockID != 0)
  380.             {
  381.                 pDockBar = (CDockBar*)m_pDockSite->GetControlBar(m_uMRUDockID);
  382.                 pDockBar->ClientToScreen(&rect);
  383.             }
  384.  
  385.             // dock it at the specified position, RecalcLayout will snap
  386.             m_pDockSite->ReDockControlBar(m_pBar, pDockBar, &rect);
  387.             m_pDockSite->RecalcLayout();
  388.         }
  389.     }
  390.     else
  391.     {
  392.         CPoint ptFloat = m_ptMRUFloatPos;
  393.         if (ptFloat.x < 0 || ptFloat.y < 0)
  394.         {
  395.             ptFloat = m_rectMRUDockPos.TopLeft();
  396.             m_pBar->GetParent()->ClientToScreen(&ptFloat);
  397.         }
  398.         m_pDockSite->FloatControlBar(m_pBar, ptFloat, m_dwMRUFloatStyle);
  399.     }
  400. }
  401.  
  402. /////////////////////////////////////////////////////////////////////////////
  403. // CDockContext Operations
  404.  
  405. void CDockContext::InitLoop()
  406. {
  407.     // handle pending WM_PAINT messages
  408.     MSG msg;
  409.     while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  410.     {
  411.         if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  412.             return;
  413.         DispatchMessage(&msg);
  414.     }
  415.  
  416.     // get styles from bar
  417.     m_dwDockStyle = m_pBar->m_dwDockStyle;
  418.     m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY;
  419.     ASSERT(m_dwStyle != 0);
  420.  
  421.     // initialize state
  422.     m_rectLast.SetRectEmpty();
  423.     m_sizeLast.cx = m_sizeLast.cy = 0;
  424.     m_bForceFrame = m_bFlip = m_bDitherLast = FALSE;
  425.  
  426.     // lock window update while dragging
  427.     ASSERT(m_pDC == NULL);
  428.     CWnd* pWnd = CWnd::GetDesktopWindow();
  429.     if (pWnd->LockWindowUpdate())
  430.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  431.     else
  432.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
  433.     ASSERT(m_pDC != NULL);
  434. }
  435.  
  436. void CDockContext::CancelLoop()
  437. {
  438.     DrawFocusRect(TRUE);    // gets rid of focus rect
  439.     ReleaseCapture();
  440.  
  441.     CWnd* pWnd = CWnd::GetDesktopWindow();
  442.     pWnd->UnlockWindowUpdate();
  443.     if (m_pDC != NULL)
  444.     {
  445.         pWnd->ReleaseDC(m_pDC);
  446.         m_pDC = NULL;
  447.     }
  448. }
  449.  
  450. /////////////////////////////////////////////////////////////////////////////
  451. // Implementation
  452.  
  453. void CDockContext::DrawFocusRect(BOOL bRemoveRect)
  454. {
  455.     ASSERT(m_pDC != NULL);
  456.  
  457.     // default to thin frame
  458.     CSize size(CX_BORDER, CY_BORDER);
  459.  
  460.     // determine new rect and size
  461.     CRect rect;
  462.     CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
  463.     CBrush* pDitherBrush = CDC::GetHalftoneBrush();
  464.     CBrush* pBrush = pWhiteBrush;
  465.  
  466.     if (HORZF(m_dwOverDockStyle))
  467.         rect = m_rectDragHorz;
  468.     else if (VERTF(m_dwOverDockStyle))
  469.         rect = m_rectDragVert;
  470.     else
  471.     {
  472.         // use thick frame instead
  473.         size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER;
  474.         size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER;
  475.         if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
  476.             rect = m_rectFrameDragHorz;
  477.         else
  478.             rect = m_rectFrameDragVert;
  479.         pBrush = pDitherBrush;
  480.     }
  481.     if (bRemoveRect)
  482.         size.cx = size.cy = 0;
  483.  
  484.     if (afxData.bWin4 &&
  485.         (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle)))
  486.     {
  487.         // looks better one pixel in (makes the bar look pushed down)
  488.         rect.InflateRect(-CX_BORDER, -CY_BORDER);
  489.     }
  490.  
  491.     // draw it and remember last size
  492.     m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
  493.         pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
  494.     m_rectLast = rect;
  495.     m_sizeLast = size;
  496.     m_bDitherLast = (pBrush == pDitherBrush);
  497. }
  498.  
  499. void CDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue)
  500. {
  501.     if (*pFlag != bNewValue)
  502.     {
  503.         *pFlag = bNewValue;
  504.         m_bFlip = (HORZF(m_dwDockStyle) && VERTF(m_dwDockStyle) && m_bFlip); // shift key
  505.         m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock();
  506.         DrawFocusRect();
  507.     }
  508. }
  509.  
  510. DWORD CDockContext::CanDock()
  511. {
  512.     BOOL bStyleHorz;
  513.     DWORD dwDock = 0; // Dock Canidate
  514.     DWORD dwCurr = 0; // Current Orientation
  515.  
  516.     // let's check for something in our current orientation first
  517.     // then if the shift key is not forcing our orientation then
  518.     // check for horizontal or vertical orientations as long
  519.     // as we are close enough
  520.     ASSERT(m_dwStyle != 0);
  521.  
  522.     bStyleHorz = HORZF(m_dwStyle);
  523.     bStyleHorz = m_bFlip ? !bStyleHorz : bStyleHorz;
  524.  
  525.     if (bStyleHorz && HORZF(m_dwDockStyle))
  526.         dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  527.                                       m_dwDockStyle & ~CBRS_ORIENT_VERT);
  528.     else if (VERTF(m_dwDockStyle))
  529.         dwDock = m_pDockSite->CanDock(m_rectDragVert,
  530.                                       m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  531.  
  532.     if (!m_bFlip)
  533.     {
  534.         if (dwDock == 0 && HORZF(m_dwDockStyle))
  535.         {
  536.             dwCurr = m_pDockSite->CanDock(m_rectDragVert,
  537.                                           m_dwDockStyle & ~CBRS_ORIENT_VERT);
  538.             dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  539.                                           m_dwDockStyle & ~CBRS_ORIENT_VERT);
  540.             dwDock = (dwDock == dwCurr) ? dwDock : 0;
  541.         }
  542.         if (dwDock == 0 && VERTF(m_dwDockStyle))
  543.         {
  544.             dwCurr = m_pDockSite->CanDock(m_rectDragHorz,
  545.                                           m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  546.             dwDock = m_pDockSite->CanDock(m_rectDragVert,
  547.                                           m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  548.             dwDock = (dwDock == dwCurr) ? dwDock : 0;
  549.         }
  550.     }
  551.  
  552.     return dwDock;
  553. }
  554.  
  555. CDockBar* CDockContext::GetDockBar(DWORD dwOverDockStyle)
  556. {
  557.     DWORD dw = 0;
  558.     CDockBar* pBar;
  559.     if (HORZF(dwOverDockStyle))
  560.     {
  561.         dw = m_pDockSite->CanDock(m_rectDragHorz,
  562.             dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar);
  563.         ASSERT(dw != 0);
  564.         ASSERT(pBar != NULL);
  565.         return pBar;
  566.     }
  567.     if (VERTF(dwOverDockStyle))
  568.     {
  569.         dw = m_pDockSite->CanDock(m_rectDragVert,
  570.             dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar);
  571.         ASSERT(dw != 0);
  572.         ASSERT(pBar != NULL);
  573.         return pBar;
  574.     }
  575.     return NULL;
  576. }
  577.  
  578. BOOL CDockContext::Track()
  579. {
  580.     // don't handle if capture already set
  581.     if (::GetCapture() != NULL)
  582.         return FALSE;
  583.  
  584.     // set capture to the window which received this message
  585.     m_pBar->SetCapture();
  586.     ASSERT(m_pBar == CWnd::GetCapture());
  587.  
  588.     // get messages until capture lost or cancelled/accepted
  589.     while (CWnd::GetCapture() == m_pBar)
  590.     {
  591.         MSG msg;
  592.         if (!::GetMessage(&msg, NULL, 0, 0))
  593.         {
  594.             AfxPostQuitMessage(msg.wParam);
  595.             break;
  596.         }
  597.  
  598.         switch (msg.message)
  599.         {
  600.         case WM_LBUTTONUP:
  601.             if (m_bDragging)
  602.                 EndDrag();
  603.             else
  604.                 EndResize();
  605.             return TRUE;
  606.         case WM_MOUSEMOVE:
  607.             if (m_bDragging)
  608.                 Move(msg.pt);
  609.             else
  610.                 Stretch(msg.pt);
  611.             break;
  612.         case WM_KEYUP:
  613.             if (m_bDragging)
  614.                 OnKey((int)msg.wParam, FALSE);
  615.             break;
  616.         case WM_KEYDOWN:
  617.             if (m_bDragging)
  618.                 OnKey((int)msg.wParam, TRUE);
  619.             if (msg.wParam == VK_ESCAPE)
  620.             {
  621.                 CancelLoop();
  622.                 return FALSE;
  623.             }
  624.             break;
  625.         case WM_RBUTTONDOWN:
  626.             CancelLoop();
  627.             return FALSE;
  628.  
  629.         // just dispatch rest of the messages
  630.         default:
  631.             DispatchMessage(&msg);
  632.             break;
  633.         }
  634.     }
  635.  
  636.     CancelLoop();
  637.  
  638.     return FALSE;
  639. }
  640.  
  641. /////////////////////////////////////////////////////////////////////////////
  642.