home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLEDROP1.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  7.8 KB  |  281 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 <Events.h>     // for GetDblTime()
  15. #include <macname2.h>
  16. #endif
  17.  
  18. #ifdef AFX_OLE4_SEG
  19. #pragma code_seg(AFX_OLE4_SEG)
  20. #endif
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. #define new DEBUG_NEW
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // COleDropSource implementation
  31.  
  32. AFX_DATADEF UINT COleDropSource::nDragMinDist;
  33. AFX_DATADEF UINT COleDropSource::nDragDelay;
  34.  
  35. COleDropSource::COleDropSource()
  36. {
  37.     m_bDragStarted = FALSE;
  38.     m_dwButtonCancel = 0;
  39.     m_dwButtonDrop = 0;
  40.  
  41.     AfxLockGlobals(CRIT_DROPSOURCE);
  42.     static BOOL bInitialized;
  43.     if (!bInitialized)
  44.     {
  45. #ifndef _MAC
  46.         // get drag metrics from win.ini
  47.         static const TCHAR szWindows[] = _T("windows");
  48.         static const TCHAR szDragMinDist[] = _T("DragMinDist");
  49.         static const TCHAR szDragDelay[] = _T("DragDelay");
  50.  
  51.         nDragMinDist = GetProfileInt(szWindows, szDragMinDist, DD_DEFDRAGMINDIST);
  52.         nDragDelay = GetProfileInt(szWindows, szDragDelay, DD_DEFDRAGDELAY);
  53. #else
  54.         nDragMinDist = DD_DEFDRAGMINDIST;
  55.         nDragDelay = (GetDblTime() * 1000) / 60;    // convert ticks to milliseconds
  56. #endif
  57.  
  58.         // now initialized, no need to call Initialize any more
  59.         bInitialized = TRUE;
  60.     }
  61.     AfxUnlockGlobals(CRIT_DROPSOURCE);
  62.  
  63.     ASSERT_VALID(this);
  64. }
  65.  
  66. SCODE COleDropSource::QueryContinueDrag(BOOL bEscapePressed, DWORD dwKeyState)
  67. {
  68.     ASSERT_VALID(this);
  69.  
  70.     // check escape key or right button -- and cancel
  71.     if (bEscapePressed || (dwKeyState & m_dwButtonCancel) != 0)
  72.     {
  73.         m_bDragStarted = FALSE; // avoid unecessary cursor setting
  74.         return DRAGDROP_S_CANCEL;
  75.     }
  76.  
  77. #ifndef _MAC
  78.     // check left-button up to end drag/drop and do the drop
  79.     if ((dwKeyState & m_dwButtonDrop) == 0)
  80.         return m_bDragStarted ? DRAGDROP_S_DROP : DRAGDROP_S_CANCEL;
  81. #else
  82.     // check the current state of the mouse
  83.     if (!Button())
  84.         return m_bDragStarted ? DRAGDROP_S_DROP : DRAGDROP_S_CANCEL;
  85. #endif
  86.  
  87.     // otherwise, keep polling...
  88.     return S_OK;
  89. }
  90.  
  91. SCODE COleDropSource::GiveFeedback(DROPEFFECT /*dropEffect*/)
  92. {
  93.     ASSERT_VALID(this);
  94.  
  95.     // don't change the cursor until drag is officially started
  96.     return m_bDragStarted ? DRAGDROP_S_USEDEFAULTCURSORS : S_OK;
  97. }
  98.  
  99. BOOL COleDropSource::OnBeginDrag(CWnd* pWnd)
  100. {
  101.     ASSERT_VALID(this);
  102.  
  103.     m_bDragStarted = FALSE;
  104.  
  105.     // opposite button cancels drag operation
  106. #ifndef _MAC
  107.     m_dwButtonCancel = 0;
  108.     m_dwButtonDrop = 0;
  109.     if (GetKeyState(VK_LBUTTON) < 0)
  110.     {
  111.         m_dwButtonDrop |= MK_LBUTTON;
  112.         m_dwButtonCancel |= MK_RBUTTON;
  113.     }
  114.     else if (GetKeyState(VK_RBUTTON) < 0)
  115.     {
  116.         m_dwButtonDrop |= MK_RBUTTON;
  117.         m_dwButtonCancel |= MK_LBUTTON;
  118.     }
  119. #endif
  120.  
  121.     DWORD dwLastTick = GetTickCount();
  122.     pWnd->SetCapture();
  123.  
  124.     while (!m_bDragStarted)
  125.     {
  126.         // some applications steal capture away at random times
  127.         if (CWnd::GetCapture() != pWnd)
  128.             break;
  129.  
  130.         // peek for next input message
  131.         MSG msg;
  132.         if (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
  133.             PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
  134.         {
  135.             // check for button cancellation (any button down will cancel)
  136.             if (msg.message == WM_LBUTTONUP || msg.message == WM_RBUTTONUP ||
  137.                 msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN)
  138.                 break;
  139.  
  140.             // check for keyboard cancellation
  141.             if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
  142.                 break;
  143.  
  144.             // check for drag start transition
  145.             m_bDragStarted = !m_rectStartDrag.PtInRect(msg.pt);
  146.         }
  147.  
  148.         // if the user sits here long enough, we eventually start the drag
  149.         if (GetTickCount() - dwLastTick > nDragDelay)
  150.             m_bDragStarted = TRUE;
  151.     }
  152.     ReleaseCapture();
  153.  
  154.     return m_bDragStarted;
  155. }
  156.  
  157. BEGIN_INTERFACE_MAP(COleDropSource, CCmdTarget)
  158.     INTERFACE_PART(COleDropSource, IID_IDropSource, DropSource)
  159. END_INTERFACE_MAP()
  160.  
  161. STDMETHODIMP_(ULONG) COleDropSource::XDropSource::AddRef()
  162. {
  163.     METHOD_PROLOGUE_EX_(COleDropSource, DropSource)
  164.     return pThis->ExternalAddRef();
  165. }
  166.  
  167. STDMETHODIMP_(ULONG) COleDropSource::XDropSource::Release()
  168. {
  169.     METHOD_PROLOGUE_EX_(COleDropSource, DropSource)
  170.     return pThis->ExternalRelease();
  171. }
  172.  
  173. STDMETHODIMP COleDropSource::XDropSource::QueryInterface(
  174.     REFIID iid, LPVOID* ppvObj)
  175. {
  176.     METHOD_PROLOGUE_EX_(COleDropSource, DropSource)
  177.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  178. }
  179.  
  180. STDMETHODIMP COleDropSource::XDropSource::QueryContinueDrag(
  181.     THIS_ BOOL fEscapePressed, DWORD dwKeyState)
  182. {
  183.     METHOD_PROLOGUE_EX_(COleDropSource, DropSource)
  184.  
  185.     return pThis->QueryContinueDrag(fEscapePressed, dwKeyState);
  186. }
  187.  
  188. STDMETHODIMP COleDropSource::XDropSource::GiveFeedback(THIS_ DWORD dwEffect)
  189. {
  190.     METHOD_PROLOGUE_EX(COleDropSource, DropSource)
  191.     ASSERT_VALID(pThis);
  192.  
  193.     return pThis->GiveFeedback(dwEffect);
  194. }
  195.  
  196. /////////////////////////////////////////////////////////////////////////////
  197. // helper for doing drag/drop with COleDataSource object
  198.  
  199. DROPEFFECT COleDataSource::DoDragDrop(DWORD dwEffects,
  200.     LPCRECT lpRectStartDrag, COleDropSource* pDropSource)
  201. {
  202.     ASSERT_VALID(this);
  203.     if (pDropSource != NULL)
  204.         ASSERT_VALID(pDropSource);
  205.     ASSERT(lpRectStartDrag == NULL ||
  206.         AfxIsValidAddress(lpRectStartDrag, sizeof(RECT), FALSE));
  207.  
  208.     // use standard drop source implementation if one not provided
  209.     COleDropSource dropSource;
  210.     if (pDropSource == NULL)
  211.         pDropSource = &dropSource;
  212.  
  213.     // setup drag/drop sensitivity rect
  214.     pDropSource->m_bDragStarted = FALSE;
  215.  
  216.     if (lpRectStartDrag != NULL)
  217.     {
  218.         // set drop source drag start rect to parameter provided
  219.         pDropSource->m_rectStartDrag.CopyRect(lpRectStartDrag);
  220.     }
  221.     else
  222.     {
  223.         // otherwise start with default empty rectangle around current point
  224.         CPoint ptCursor;
  225.         GetCursorPos(&ptCursor);
  226.         pDropSource->m_rectStartDrag.SetRect(
  227.             ptCursor.x, ptCursor.y, ptCursor.x, ptCursor.y);
  228.     }
  229.  
  230.     if (pDropSource->m_rectStartDrag.IsRectNull())
  231.     {
  232.         // null rect specifies no OnBeginDrag wait loop
  233.         pDropSource->m_bDragStarted = TRUE;
  234.     }
  235.     else if (pDropSource->m_rectStartDrag.IsRectEmpty())
  236.     {
  237.         // empty rect specifies drag drop around starting point
  238.         pDropSource->m_rectStartDrag.InflateRect(
  239.             COleDropSource::nDragMinDist, COleDropSource::nDragMinDist);
  240.     }
  241.     ASSERT_VALID(pDropSource);
  242.  
  243.     // before calling OLE drag/drop code, wait for mouse to move outside
  244.     //  the rectangle
  245.     ASSERT_VALID(AfxGetMainWnd());
  246.     if (!pDropSource->OnBeginDrag(AfxGetMainWnd()))
  247.         return DROPEFFECT_NONE;
  248.  
  249.     // call global OLE api to do the drag drop
  250.     LPDATAOBJECT lpDataObject = (LPDATAOBJECT)GetInterface(&IID_IDataObject);
  251.     LPDROPSOURCE lpDropSource =
  252.         (LPDROPSOURCE)pDropSource->GetInterface(&IID_IDropSource);
  253.     DWORD dwResultEffect = DROPEFFECT_NONE;
  254. #ifdef _AFXDLL
  255.     _afxOLE.pfnDoDragDrop(lpDataObject, lpDropSource, dwEffects, &dwResultEffect);
  256. #else
  257.     ::DoDragDrop(lpDataObject, lpDropSource, dwEffects, &dwResultEffect);
  258. #endif
  259.     return dwResultEffect;
  260. }
  261.  
  262. /////////////////////////////////////////////////////////////////////////////
  263. // COleDropSource diagnostics
  264.  
  265. #ifdef _DEBUG
  266. void COleDropSource::Dump(CDumpContext& dc) const
  267. {
  268.     CCmdTarget::Dump(dc);
  269.  
  270.     dc << "m_bDragStarted = " << m_bDragStarted;
  271.     dc << "\nm_rectStartDrag.left = " << m_rectStartDrag.left;
  272.     dc << "\nm_rectStartDrag.top = " << m_rectStartDrag.top;
  273.     dc << "\nm_rectStartDrag.right = " << m_rectStartDrag.right;
  274.     dc << "\nm_rectStartDrag.bottom = " << m_rectStartDrag.bottom;
  275.  
  276.     dc << "\n";
  277. }
  278. #endif
  279.  
  280. /////////////////////////////////////////////////////////////////////////////
  281.