Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
3.0 KiB

  1. #include "shellprv.h"
  2. #include "duiview.h"
  3. #include "duidrag.h"
  4. CDUIDropTarget::CDUIDropTarget()
  5. {
  6. _cRef = 1;
  7. _pDT = NULL;
  8. _pNextDT = NULL;
  9. }
  10. CDUIDropTarget::~CDUIDropTarget()
  11. {
  12. _Cleanup();
  13. }
  14. HRESULT CDUIDropTarget::QueryInterface (REFIID riid, void **ppv)
  15. {
  16. static const QITAB qit[] =
  17. {
  18. QITABENT(CDUIDropTarget, IDropTarget),
  19. { 0 },
  20. };
  21. return QISearch(this, qit, riid, ppv);
  22. }
  23. ULONG CDUIDropTarget::AddRef (void)
  24. {
  25. return ++_cRef;
  26. }
  27. ULONG CDUIDropTarget::Release (void)
  28. {
  29. if (--_cRef == 0) {
  30. delete this;
  31. return 0;
  32. }
  33. return _cRef;
  34. }
  35. // Called by duser / directui to get the IDropTarget interface for the element
  36. // the mouse just moved over. It is important to understand the sequencing
  37. // calls. Initialize is called BEFORE DragLeave is called on the previous element's
  38. // IDropTarget, so we can't switch out _pDT right away. Instead, we'll store the
  39. // new IDropTarget in _pNextDT and then in DragEnter, we'll move it over to _pDT.
  40. //
  41. // The sequence looks like this:
  42. //
  43. // Initialize() for first element (bumps ref count to 2)
  44. // DragEnter
  45. // DragMove
  46. // Initialize() for second element (bumps ref count to 3)
  47. // DragLeave for first element
  48. // Release for first element (decrements ref count to 2)
  49. // DragEnter for second element
  50. HRESULT CDUIDropTarget::Initialize (LPITEMIDLIST pidl, HWND hWnd, IDropTarget **pdt)
  51. {
  52. ASSERT(_pNextDT == NULL);
  53. if (pidl)
  54. {
  55. SHGetUIObjectFromFullPIDL(pidl, hWnd, IID_PPV_ARG(IDropTarget, &_pNextDT));
  56. }
  57. QueryInterface (IID_PPV_ARG(IDropTarget, pdt));
  58. return S_OK;
  59. }
  60. VOID CDUIDropTarget::_Cleanup ()
  61. {
  62. if (_pDT)
  63. {
  64. _pDT->Release();
  65. _pDT = NULL;
  66. }
  67. }
  68. STDMETHODIMP CDUIDropTarget::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  69. {
  70. if ((_pDT != _pNextDT) || (_cRef == 2))
  71. {
  72. _pDT = _pNextDT;
  73. _pNextDT = NULL;
  74. if (_pDT)
  75. {
  76. _pDT->DragEnter (pDataObj, grfKeyState, ptl, pdwEffect);
  77. }
  78. else
  79. {
  80. *pdwEffect = DROPEFFECT_NONE;
  81. }
  82. POINT pt;
  83. GetCursorPos(&pt);
  84. DAD_DragEnterEx2 (NULL, pt, pDataObj);
  85. }
  86. return S_OK;
  87. }
  88. STDMETHODIMP CDUIDropTarget::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  89. {
  90. if (_pDT)
  91. {
  92. _pDT->DragOver (grfKeyState, ptl, pdwEffect);
  93. }
  94. else
  95. {
  96. *pdwEffect = DROPEFFECT_NONE;
  97. }
  98. POINT pt;
  99. GetCursorPos(&pt);
  100. DAD_DragMove (pt);
  101. return S_OK;
  102. }
  103. STDMETHODIMP CDUIDropTarget::DragLeave(void)
  104. {
  105. if (_pDT || (_cRef == 2))
  106. {
  107. if (_pDT)
  108. {
  109. _pDT->DragLeave ();
  110. }
  111. DAD_DragLeave();
  112. _Cleanup();
  113. }
  114. return S_OK;
  115. }
  116. STDMETHODIMP CDUIDropTarget::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  117. {
  118. POINT pt = {ptl.x, ptl.y};
  119. HRESULT hr = S_OK;
  120. if (_pDT)
  121. {
  122. hr = _pDT->Drop (pDataObj, grfKeyState, ptl, pdwEffect);
  123. }
  124. return hr;
  125. }