home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / C / MRCE / SOURCE.ZIP / DRAGDOCK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-10  |  18.5 KB  |  565 lines

  1. // MRCEXT: Micro Focus Extension DLL for MFC 2.1+
  2. // Copyright (C)1994-5    Micro Focus Inc, 2465 East Bayshore Rd, Palo Alto, CA 94303.
  3. // 
  4. //  This program is free software; you can redistribute it and/or modify
  5. //  it under the terms of the GNU General Public License as published by
  6. //  the Free Software Foundation. In addition, you may also charge for any
  7. //  application    using MRCEXT, and are under no obligation to supply source
  8. //  code. You must accredit Micro Focus Inc in the "About Box", or banner
  9. //  of your application. 
  10. //
  11. //  This program is distributed in the hope that it will be useful,
  12. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. //  GNU General Public License for more details.
  15. //
  16. //  You should also have received a copy of the GNU General Public License with this
  17. //  software, also indicating additional rights you have when using MRCEXT.  
  18. //
  19. //
  20. // DRAGDOCK.CPP
  21. // $Date:   10 Jan 1996 12:11:18  $
  22. // $Revision:   1.2  $
  23. // $Author:   MRC  $
  24. // CDragDockContext class
  25. //
  26. // This replaces the MFC CDockContext class. It provides the "dragging" user interface,
  27. // and includes some extra features that try to indicate exactly where a bar will
  28. // dock. 
  29. //
  30. // The gateway MFC gives us to work with is:
  31. // 1) CControlBar::EnableDocking() creates the dock context for the control bar - so it's
  32. //    important to use the CMRC...Frame.. implementation of EnableDocking().
  33. //
  34. // 2) Other than the constructor/destructor, the only function access outside this class 
  35. //    is to StartDrag(CPoint pt), called when we want to start dragging the control bar.
  36. //     
  37. // The other important tie-ins are the call to Dock/Float control bar which we need to handle
  38. // with the same interpretation of parameters as the existing MFC implementation.
  39.  
  40. #include "mrcstafx.h"
  41. #include "mrcext.h"
  42. #include "mrcpriv.h"
  43. #include "mrcresrc.h"
  44.  
  45. extern MRC_AUX_DATA afxData;
  46.  
  47. #define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
  48. #define VERTF(dw) (dw & CBRS_ORIENT_VERT)
  49.  
  50. static void AdjustRectangle(CRect& rect, CPoint pt)
  51. // adjust supplied rectangle, so that point, pt is inside it.
  52. {
  53.     int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  54.                                         (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  55.     int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  56.                                       (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  57.     rect.OffsetRect(nXOffset, nYOffset);
  58. }
  59.  
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CDragDockContext
  62. // static members
  63.  
  64. CDragDockContext::CDragDockContext(CControlBar* pBar) : CDockContext(pBar)
  65. {
  66. }
  67.  
  68.  
  69. CDragDockContext::~CDragDockContext()
  70. {
  71. }
  72.  
  73.  
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CDragDockContext operations
  76.  
  77. //---------------------------------------------------------------------------
  78. void CDragDockContext::StartDrag(CPoint pt)
  79. // start dragging. This is the only routine exposed externally. 
  80. // pt = mouse position at start of drag (screen co-ords) 
  81. //---------------------------------------------------------------------------
  82. {
  83.        ASSERT_VALID(m_pBar);
  84.        ASSERT(m_pBar->IsKindOf(RUNTIME_CLASS(CMRCSizeControlBar)));
  85.    
  86.        CMRCSizeControlBar *pSzBar = (CMRCSizeControlBar *) m_pBar;
  87.  
  88.     // get styles from bar
  89.        m_dwDockStyle = m_pBar->m_dwDockStyle;
  90.        m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY;
  91.        ASSERT(m_dwStyle != 0);
  92.  
  93.     // check to see we're not hanging from a CMRCMDIFloatWnd. Disallow dragging if we are...
  94.     if (m_pBar->IsFloating())
  95.     {
  96.         CFrameWnd * pFrameWnd = m_pBar->GetParentFrame();
  97.         ASSERT(pFrameWnd != NULL);
  98.         ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)));
  99.         if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CMRCMDIFloatWnd)))
  100.             return;                // do nothing if floating inside a CMRCMDIFloatWnd
  101.     }
  102.  
  103.    // dragging has started message (only if window will actually dock !)
  104.     if ((m_dwDockStyle & CBRS_ALIGN_ANY) != 0)
  105.         AfxGetMainWnd()->SendMessage(WM_SETMESSAGESTRING, IDS_MRC_STARTDOCKING);
  106.  
  107.     // handle pending WM_PAINT messages
  108.     MSG msg;
  109.     while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  110.     {
  111.         if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  112.             return;
  113.         ASSERT(msg.message == WM_PAINT);
  114.         DispatchMessage(&msg);
  115.        }
  116.  
  117.     // initialize drag state
  118.        m_rectLast.SetRectEmpty();
  119.        m_sizeLast.cx = m_sizeLast.cy = 0;
  120.        m_bForceFrame = m_bFlip = m_bDitherLast = FALSE;
  121.  
  122.  
  123.        // get current bar location 
  124.        CRect rect;
  125.        m_pBar->GetWindowRect(rect);
  126.        m_ptLast = pt;
  127.        m_ptStart = pt;
  128.     BOOL bHorz = HORZF(m_dwStyle);
  129.  
  130.        // MFC includes code for flipping orientation using the shift key - I wasn't keen
  131.     // on this... (sorry) so I've left it out for now. Some references are still left
  132.     // in for it, in case I decide to implement it.
  133.        
  134.        // Start by working out the possible rectangles that dragging could result in.
  135.     // These are:
  136.     // m_rectFrameDragHorz    : floating frame, horizontal orientation
  137.     // m_rectFrameDragVert    : floating frame, vertical orientation (not used, 'cos
  138.     //                                    flipping not allowed)
  139.     //
  140.     // m_rectDragHorz        : docking horizontally, another bar already on this row
  141.     // m_rectDragVert        : docking vertically, another bar already on this row
  142.     
  143.     // m_rectDragHorzAlone  : docking horizontally, on a new row
  144.     // m_rectDragVertAlone  : docking vertically, on a new row
  145.     
  146.     
  147.     // calculate the size of the docking area, used below
  148.     // FIXME: for now I'm just using the CFrameWnd client area.
  149.     CRect rcFrameClient;
  150.     m_pDockSite->GetClientRect(rcFrameClient);    
  151.     m_pDockSite->ClientToScreen(rcFrameClient);
  152.     int nDockAreaWidth = rcFrameClient.Width();
  153.     int nDockAreaHeight = rcFrameClient.Height();
  154.  
  155.     CSize HorzAloneSize(nDockAreaWidth, pSzBar->m_HorzDockSize.cy);
  156.     CSize VertAloneSize(pSzBar->m_VertDockSize.cx, nDockAreaHeight);
  157.     
  158.     m_rectDragHorzAlone = CRect(CPoint(rcFrameClient.left, rect.top), HorzAloneSize);
  159.     m_rectDragVertAlone = CRect(CPoint(rect.left, rcFrameClient.top),  VertAloneSize);
  160.  
  161.     // sizes to use when docking into a row that already has some bars.
  162.     // use the stored sizes - unless they are > the max dock area - in which case make a guess.
  163.     if (pSzBar->m_VertDockSize.cy >= nDockAreaHeight - 16)
  164.         VertAloneSize.cy = nDockAreaHeight / 2;
  165.     else 
  166.         VertAloneSize.cy = pSzBar->m_VertDockSize.cy;
  167.  
  168.     if (pSzBar->m_HorzDockSize.cx >= nDockAreaWidth - 16)
  169.         HorzAloneSize.cx = nDockAreaWidth / 2;
  170.     else
  171.         HorzAloneSize.cx = pSzBar->m_HorzDockSize.cx;
  172.     
  173.     m_rectDragHorz = CRect(rect.TopLeft(), HorzAloneSize);
  174.     m_rectDragVert = CRect(rect.TopLeft(), VertAloneSize);
  175.  
  176.  
  177.        // rectangle for the floating frame...
  178.        m_rectFrameDragHorz = CRect(rect.TopLeft(), pSzBar->m_FloatSize);
  179.        m_rectFrameDragVert = m_rectFrameDragHorz;
  180.        
  181.        // To work out the size we actually create a floating mini frame, and then see how big
  182.        // it is
  183.     CMiniDockFrameWnd* pFloatFrame =
  184.            m_pDockSite->CreateFloatingFrame(bHorz ? CBRS_ALIGN_TOP : CBRS_ALIGN_LEFT);
  185.        if (pFloatFrame == NULL)
  186.         AfxThrowMemoryException();
  187.        pFloatFrame->CalcWindowRect(&m_rectFrameDragHorz);
  188.        pFloatFrame->CalcWindowRect(&m_rectFrameDragVert);
  189.        m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  190.        m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  191.        pFloatFrame->DestroyWindow();
  192.  
  193.        // adjust rectangles so that point is inside
  194.        AdjustRectangle(m_rectDragHorz, pt);
  195.        AdjustRectangle(m_rectDragVert, pt);
  196.        AdjustRectangle(m_rectDragHorzAlone, pt);
  197.        AdjustRectangle(m_rectDragVertAlone, pt);
  198.        AdjustRectangle(m_rectFrameDragHorz, pt);
  199.        AdjustRectangle(m_rectFrameDragVert, pt);
  200.  
  201.        // lock window update while dragging
  202.        ASSERT(m_pDC == NULL);
  203.        CWnd* pWnd = CWnd::GetDesktopWindow();
  204. #ifndef _MAC
  205.     if (pWnd->LockWindowUpdate())
  206.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  207.     else
  208. #endif
  209.         m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
  210.     ASSERT(m_pDC != NULL);
  211.  
  212.         // initialize tracking state and enter tracking loop
  213.     m_dwOverDockStyle = CanDock();
  214.     Move(pt);   // call it here to handle special keys
  215.     Track();
  216. }
  217.  
  218.  
  219. void CDragDockContext::Move(CPoint pt)
  220. {
  221.     CPoint ptOffset = pt - m_ptLast;
  222.  
  223. #ifdef _MAC
  224.     // prevent dragging the floating window completely under the menu bar
  225.     GDHandle hgd = _AfxFindDevice(pt.x, pt.y);
  226.     if (hgd == NULL || hgd == GetMainDevice() ||
  227.                         TestDeviceAttribute(hgd, hasAuxMenuBar))
  228.     {
  229.         CRect rect;
  230.  
  231.         if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
  232.             rect = m_rectFrameDragHorz;
  233.         else
  234.             rect = m_rectFrameDragVert;
  235.  
  236.         // determine our new position
  237.         rect.OffsetRect(ptOffset);
  238.  
  239.         // keep us on the screen if we were getting too close to the menu bar
  240.         int yMBarBottom = (*hgd)->gdRect.top + GetMBarHeight() + 4;
  241.         if (rect.bottom < yMBarBottom)
  242.         {
  243.             pt.y += yMBarBottom - rect.bottom;
  244.             ptOffset.y += yMBarBottom - rect.bottom;
  245.         }
  246.     }
  247. #endif
  248.  
  249.     // offset all drag rects to new position
  250.     m_rectDragHorz.OffsetRect(ptOffset);
  251.     m_rectFrameDragHorz.OffsetRect(ptOffset);
  252.     m_rectDragVert.OffsetRect(ptOffset);
  253.     m_rectFrameDragVert.OffsetRect(ptOffset);
  254.     
  255.     // these rectangles only move in 1 direction
  256.     m_rectDragHorzAlone.top += ptOffset.y;
  257.     m_rectDragHorzAlone.bottom += ptOffset.y;
  258.     m_rectDragVertAlone.left  += ptOffset.x;
  259.     m_rectDragVertAlone.right += ptOffset.x;
  260.  
  261.     m_rectDragDock.OffsetRect(ptOffset);    // new...
  262.     m_ptLast = pt;
  263.  
  264.     // if control key is down don't dock
  265.     m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
  266.  
  267.     // update feedback
  268.     DrawFocusRect();
  269. }
  270.  
  271.  
  272. void CDragDockContext::OnKey(int nChar, BOOL bDown)
  273. {
  274.     if (nChar == VK_CONTROL)
  275.         UpdateState(&m_bForceFrame, bDown);
  276. }
  277.  
  278.  
  279. void CDragDockContext::EndDrag()
  280. {
  281.     CancelDrag();
  282.     if (m_ptStart == m_ptLast)
  283.         return;
  284.  
  285.    m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
  286.     if (m_dwOverDockStyle != 0)
  287.     {
  288.         CDockBar* pDockBar = GetDockBar();
  289.         ASSERT(pDockBar != NULL);
  290.         // Now we're going to actually dock the window.
  291.  
  292.         // Update the appropriate size in the control bar.
  293.         // Rely on the layout recalculation to spot a window has moved and recalculate
  294.         // the layout. We could perhaps ensure space in the appropriate dockbar at this
  295.         // point, rather than let the layout recalculation behave as default.
  296.         if (HORZF(m_dwOverDockStyle)) 
  297.             ((CMRCSizeControlBar *) m_pBar)->m_HorzDockSize = m_rectDragDock.Size();
  298.         else
  299.             ((CMRCSizeControlBar *) m_pBar)->m_VertDockSize = m_rectDragDock.Size();
  300.  
  301.         m_pDockSite->DockControlBar(m_pBar, pDockBar, m_rectDragDock);
  302.         
  303.         // if into a sizeable dockbar (always will be, then adjust other bars in the same row
  304.         // to attempt to maintain size
  305.         if (pDockBar->IsKindOf(RUNTIME_CLASS(CSizeDockBar)))
  306.             ((CSizeDockBar *)pDockBar)->AdjustForNewBar(m_pBar);
  307.         
  308.         m_pDockSite->RecalcLayout();
  309.     }
  310.     else
  311.     {
  312.         m_pDockSite->FloatControlBar(m_pBar, m_rectFrameDragHorz.TopLeft(),
  313.                         CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI));
  314.  
  315.         // set flag to indicate user has moved the bar - done as a style flag on the window.
  316.         CWnd * pFrameWnd = m_pBar->GetParentFrame();
  317.         ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)));
  318.         pFrameWnd->ModifyStyle(0, CBRS_MOVED_BY_USER);        
  319.     }
  320.     
  321. }
  322.  
  323.  
  324. void CDragDockContext::CancelDrag()
  325. {
  326.     DrawFocusRect(TRUE);    // gets rid of focus rect
  327.     ReleaseCapture();
  328.  
  329.     CWnd* pWnd = CWnd::GetDesktopWindow();
  330. #ifndef _MAC
  331.     pWnd->UnlockWindowUpdate();
  332. #endif
  333.     if (m_pDC != NULL)
  334.     {
  335.         pWnd->ReleaseDC(m_pDC);
  336.         m_pDC = NULL;
  337.     }
  338.  
  339.     // Tell main window to clear it's status bar
  340.     CWnd *pMainWnd = AfxGetMainWnd();
  341.     ASSERT(pMainWnd != NULL);
  342.     pMainWnd->SendMessage(WM_SETMESSAGESTRING, (WPARAM)AFX_IDS_IDLEMESSAGE);
  343. }
  344.  
  345.  
  346. /////////////////////////////////////////////////////////////////////////////
  347. // Implementation
  348.  
  349. void CDragDockContext::DrawFocusRect(BOOL bRemoveRect)
  350. {
  351.     ASSERT(m_pDC != NULL);
  352.  
  353.     // default to thin frame
  354.     CSize size(CX_BORDER, CY_BORDER);
  355.  
  356.     // determine new rect and size
  357.     CRect rect;
  358.     CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
  359.     CBrush* pDitherBrush = CDC::GetHalftoneBrush();
  360.     CBrush* pBrush = pWhiteBrush;
  361.  
  362.     if (m_dwOverDockStyle != 0)
  363.     {
  364.         rect = m_rectDragDock;
  365.     }
  366.  /* if (HORZF(m_dwOverDockStyle))
  367.         rect = m_rectDragHorz;
  368.     else if (VERTF(m_dwOverDockStyle))
  369.             rect = m_rectDragVert; */
  370.     else
  371.     {
  372. #ifndef _MAC
  373.         // use thick frame instead
  374.         size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER;
  375.         size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER;
  376. #endif
  377.         rect = m_rectFrameDragHorz;
  378.         pBrush = pDitherBrush;
  379.     }
  380.     if (bRemoveRect)
  381.         size.cx = size.cy = 0;
  382.  
  383.     if ( /*afxData.bWin4 &&         */
  384.                 (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle)))
  385.     {
  386.     // looks better one pixel in (makes the bar look pushed down)
  387.         rect.InflateRect(-CX_BORDER, -CY_BORDER);
  388.     }
  389.  
  390.     // draw it and remember last size
  391.     m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
  392.                 pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
  393.     m_rectLast = rect;
  394.     m_sizeLast = size;
  395.     m_bDitherLast = (pBrush == pDitherBrush);
  396. }
  397.  
  398.  
  399. void CDragDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue)
  400. {
  401.     if (*pFlag != bNewValue)
  402.     {
  403.         *pFlag = bNewValue;
  404.         // m_bFlip = (HORZF(m_dwDockStyle) && VERTF(m_dwDockStyle) && m_bFlip); // shift key
  405.         m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock();
  406.         DrawFocusRect();
  407.     }
  408. }
  409.  
  410.  
  411. DWORD CDragDockContext::CanDock()
  412. {
  413.     BOOL bStyleHorz;
  414.     DWORD dwDock = 0; // Dock Canidate
  415.     DWORD dwCurr = 0; // Current Orientation
  416.  
  417.     // let's check for something in our current orientation first
  418.     // then if the shift key is not forcing our orientation then
  419.     // check for horizontal or vertical orientations as long
  420.     // as we are close enough
  421.     ASSERT(m_dwStyle != 0);
  422.  
  423.     bStyleHorz = HORZF(m_dwStyle);
  424.  
  425.     m_pTargetDockBar = NULL;
  426.  
  427.     /*
  428.     if (bStyleHorz && HORZF(m_dwDockStyle))
  429.         dwDock = m_pDockSite->CanDock(m_rectDragHorzAlone,
  430.                                         m_dwDockStyle & ~CBRS_ORIENT_VERT, (CDockBar **)&m_pTargetDockBar);
  431.     
  432.     
  433.     else if (VERTF(m_dwDockStyle))
  434.             dwDock = m_pDockSite->CanDock(m_rectDragVertAlone,
  435.                                          m_dwDockStyle & ~CBRS_ORIENT_HORZ, (CDockBar **)&m_pTargetDockBar);
  436.       */
  437.     // can simplify this, 'cos most of the rectangles are actually the same
  438.     if (dwDock == 0 && HORZF(m_dwDockStyle) && m_rectDragHorzAlone.PtInRect(m_ptLast))
  439.     {
  440.         dwDock = m_pDockSite->CanDock(m_rectDragHorzAlone,
  441.                              m_dwDockStyle & ~CBRS_ORIENT_VERT, (CDockBar **)&m_pTargetDockBar);
  442.     }
  443.     if (dwDock == 0 && VERTF(m_dwDockStyle) && m_rectDragVertAlone.PtInRect(m_ptLast))
  444.     {
  445.         dwDock = m_pDockSite->CanDock(m_rectDragVertAlone,
  446.                             m_dwDockStyle & ~CBRS_ORIENT_HORZ, (CDockBar **)&m_pTargetDockBar);
  447.     }
  448.  
  449.     if (dwDock != 0)    // will dock somewhere - now look for 1/2 bars on the row...
  450.     {
  451.         if (HORZF(dwDock))
  452.         {
  453.             m_rectDragDock = m_rectDragHorzAlone;
  454.             dwCurr = m_pDockSite->CanDock(m_rectDragHorz, 
  455.                                 m_dwDockStyle & ~CBRS_ORIENT_VERT, (CDockBar **)&m_pTargetDockBar);
  456.             if (dwCurr != 0)
  457.                 if (m_pTargetDockBar->BarsOnThisRow (m_pBar, m_rectDragHorzAlone) != 0)
  458.                     m_rectDragDock = m_rectDragHorz;
  459.         }        
  460.         
  461.         if (VERTF(dwDock))
  462.         {
  463.             m_rectDragDock = m_rectDragVertAlone;
  464.             dwCurr = m_pDockSite->CanDock(m_rectDragVert, 
  465.                                 m_dwDockStyle & ~CBRS_ORIENT_HORZ, (CDockBar **)&m_pTargetDockBar);
  466.             if (dwCurr != 0)
  467.                 if (m_pTargetDockBar->BarsOnThisRow (m_pBar, m_rectDragVertAlone) != 0)
  468.                     m_rectDragDock = m_rectDragVert;
  469.         }        
  470.     }
  471.  
  472.     return dwDock;
  473. }
  474.  
  475.  
  476. CDockBar* CDragDockContext::GetDockBar()
  477. {
  478.     DWORD dw = 0;
  479.     CDockBar* pBar;
  480.     if (HORZF(m_dwOverDockStyle))
  481.     {
  482.         dw = m_pDockSite->CanDock(m_rectDragHorz,
  483.                         m_dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar);
  484.         ASSERT(dw != 0);
  485.         ASSERT(pBar != NULL);
  486.         return pBar;
  487.     }
  488.     if (VERTF(m_dwOverDockStyle))
  489.     {
  490.         dw = m_pDockSite->CanDock(m_rectDragVert,
  491.                         m_dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar);
  492.         ASSERT(dw != 0);
  493.         ASSERT(pBar != NULL);
  494.         return pBar;
  495.     }
  496.     return NULL;
  497. }
  498.  
  499.  
  500. //-------------------------------------------------------------------------------
  501. BOOL CDragDockContext::Track()
  502. //-------------------------------------------------------------------------------
  503. {
  504.     // don't handle if capture already set
  505.     if (::GetCapture() != NULL)
  506.         return FALSE;
  507.  
  508.     // set capture to the window which received this message
  509.     m_pBar->SetCapture();
  510.     ASSERT(m_pBar == CWnd::GetCapture());
  511.  
  512.     // get messages until capture lost or cancelled/accepted
  513.     while(CWnd::GetCapture() == m_pBar)
  514.     {
  515.         MSG msg;
  516. #ifndef _MAC
  517.         if (!::GetMessage(&msg, NULL, 0, 0))
  518. #else
  519.         // don't allow yielding while tracking since we don't have LockWindowUpdate
  520.         if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE|PM_NOYIELD))
  521.             continue;
  522.         if (msg.message == WM_QUIT)
  523. #endif
  524.         {
  525.             AfxPostQuitMessage(msg.wParam);
  526.             break;
  527.         }
  528.  
  529.         switch (msg.message)
  530.         {
  531.             case WM_LBUTTONUP:        // drag finished 
  532.                 EndDrag();
  533.                 return TRUE;
  534.             
  535.             case WM_MOUSEMOVE:
  536.                 Move(msg.pt);
  537.                 break;
  538.             
  539.             case WM_KEYUP:
  540.                 OnKey((int)msg.wParam, FALSE);
  541.                 break;
  542.             
  543.             case WM_KEYDOWN:
  544.                   OnKey((int)msg.wParam, TRUE);
  545.                 if (msg.wParam == VK_ESCAPE)
  546.                     goto exit_cancel_drag;
  547.                 break;
  548.             
  549.             case WM_RBUTTONDOWN:
  550.                 goto exit_cancel_drag;
  551.  
  552.             // just dispatch rest of the messages
  553.             default:
  554.                 DispatchMessage(&msg);
  555.                 break;
  556.         }
  557.     }
  558.     
  559. exit_cancel_drag:            // goto  - can't use break as we're inside a switch()    
  560.     CancelDrag();
  561.     return FALSE;
  562. }
  563.  
  564. IMPLEMENT_DYNAMIC(CSizeDockBar, CDockBar)
  565.