oledrop1.cpp 7.3 KB

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