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.

674 lines
19 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Sample Code
  4. **
  5. ** dragdrop.c
  6. **
  7. ** This file contains the major interfaces, methods and related support
  8. ** functions for implementing Drag/Drop. The code contained in this
  9. ** file is used by BOTH the Container and Server (Object) versions
  10. ** of the Outline sample code.
  11. ** The Drag/Drop support includes the following implementation objects:
  12. **
  13. ** OleDoc Object
  14. ** exposed interfaces:
  15. ** IDropSource
  16. ** IDropTarget
  17. **
  18. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  19. **
  20. *************************************************************************/
  21. #include "outline.h"
  22. OLEDBGDATA
  23. extern LPOUTLINEAPP g_lpApp;
  24. #if defined( USE_DRAGDROP )
  25. /* OleDoc_QueryDrag
  26. * ----------------
  27. * Check to see if Drag operation should be initiated. A Drag operation
  28. * should be initiated when the mouse in either the top 10 pixels of the
  29. * selected list box entry or in the bottom 10 pixels of the last selected
  30. * item.
  31. */
  32. BOOL OleDoc_QueryDrag(LPOLEDOC lpOleDoc, int y)
  33. {
  34. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  35. LINERANGE LineRange;
  36. if ( LineList_GetSel( lpLL, (LPLINERANGE)&LineRange) ) {
  37. RECT rect;
  38. if (!LineList_GetLineRect(lpLL,LineRange.m_nStartLine,(LPRECT)&rect))
  39. return FALSE ;
  40. if ( rect.top <= y && y <= rect.top + DD_SEL_THRESH )
  41. return TRUE;
  42. LineList_GetLineRect( lpLL, LineRange.m_nEndLine, (LPRECT)&rect );
  43. if ( rect.bottom >= y && y >= rect.bottom - DD_SEL_THRESH )
  44. return TRUE;
  45. }
  46. return FALSE;
  47. }
  48. /* OleDoc_DoDragScroll
  49. * -------------------
  50. * Check to see if Drag scroll operation should be initiated. A Drag scroll
  51. * operation should be initiated when the mouse has remained in the active
  52. * scroll area (11 pixels frame around border of window) for a specified
  53. * amount of time (50ms).
  54. */
  55. BOOL OleDoc_DoDragScroll(LPOLEDOC lpOleDoc, POINTL pointl)
  56. {
  57. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  58. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  59. HWND hWndListBox = LineList_GetWindow(lpLL);
  60. DWORD dwScrollDir = SCROLLDIR_NULL;
  61. DWORD dwTime = GetCurrentTime();
  62. int nScrollInset = lpOleApp->m_nScrollInset;
  63. int nScrollDelay = lpOleApp->m_nScrollDelay;
  64. int nScrollInterval = lpOleApp->m_nScrollInterval;
  65. POINT point;
  66. RECT rect;
  67. if ( lpLL->m_nNumLines == 0 )
  68. return FALSE;
  69. point.x = (int)pointl.x;
  70. point.y = (int)pointl.y;
  71. ScreenToClient( hWndListBox, &point);
  72. GetClientRect ( hWndListBox, (LPRECT) &rect );
  73. if (rect.top <= point.y && point.y<=(rect.top+nScrollInset))
  74. dwScrollDir = SCROLLDIR_UP;
  75. else if ((rect.bottom-nScrollInset) <= point.y && point.y <= rect.bottom)
  76. dwScrollDir = SCROLLDIR_DOWN;
  77. if (lpOleDoc->m_dwTimeEnterScrollArea) {
  78. /* cursor was already in Scroll Area */
  79. if (! dwScrollDir) {
  80. /* cusor moved OUT of scroll area.
  81. ** clear "EnterScrollArea" time.
  82. */
  83. lpOleDoc->m_dwTimeEnterScrollArea = 0L;
  84. lpOleDoc->m_dwNextScrollTime = 0L;
  85. lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL;
  86. } else if (dwScrollDir != lpOleDoc->m_dwLastScrollDir) {
  87. /* cusor moved into a different direction scroll area.
  88. ** reset "EnterScrollArea" time to start a new 50ms delay.
  89. */
  90. lpOleDoc->m_dwTimeEnterScrollArea = dwTime;
  91. lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay;
  92. lpOleDoc->m_dwLastScrollDir = dwScrollDir;
  93. } else if (dwTime && dwTime >= lpOleDoc->m_dwNextScrollTime) {
  94. LineList_Scroll ( lpLL, dwScrollDir ); // Scroll doc NOW
  95. lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollInterval;
  96. }
  97. } else {
  98. if (dwScrollDir) {
  99. /* cusor moved INTO a scroll area.
  100. ** reset "EnterScrollArea" time to start a new 50ms delay.
  101. */
  102. lpOleDoc->m_dwTimeEnterScrollArea = dwTime;
  103. lpOleDoc->m_dwNextScrollTime = dwTime + (DWORD)nScrollDelay;
  104. lpOleDoc->m_dwLastScrollDir = dwScrollDir;
  105. }
  106. }
  107. return (dwScrollDir ? TRUE : FALSE);
  108. }
  109. /* OleDoc_QueryDrop
  110. ** ----------------
  111. ** Check if the desired drop operation (identified by the given key
  112. ** state) is possible at the current mouse position (pointl).
  113. */
  114. BOOL OleDoc_QueryDrop (
  115. LPOLEDOC lpOleDoc,
  116. DWORD grfKeyState,
  117. POINTL pointl,
  118. BOOL fDragScroll,
  119. LPDWORD lpdwEffect
  120. )
  121. {
  122. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  123. LINERANGE linerange;
  124. short nIndex = LineList_GetLineIndexFromPointl( lpLL, pointl );
  125. DWORD dwScrollEffect = 0L;
  126. DWORD dwOKEffects = *lpdwEffect;
  127. /* check if the cursor is in the active scroll area, if so need the
  128. ** special scroll cursor.
  129. */
  130. if (fDragScroll)
  131. dwScrollEffect = DROPEFFECT_SCROLL;
  132. /* if we have already determined that the source does NOT have any
  133. ** acceptable data for us, the return NO-DROP
  134. */
  135. if (! lpOleDoc->m_fCanDropCopy && ! lpOleDoc->m_fCanDropLink)
  136. goto dropeffect_none;
  137. /* if the Drag/Drop is local to our document, we can NOT accept a
  138. ** drop in the middle of the current selection (which is the exact
  139. ** data that is being dragged!).
  140. */
  141. if (lpOleDoc->m_fLocalDrag) {
  142. LineList_GetSel( lpLL, (LPLINERANGE)&linerange );
  143. if (linerange.m_nStartLine <= nIndex && nIndex<linerange.m_nEndLine)
  144. goto dropeffect_none;
  145. }
  146. /* OLE2NOTE: determine what type of drop should be performed given
  147. ** the current modifier key state. we rely on the standard
  148. ** interpretation of the modifier keys:
  149. ** no modifier -- DROPEFFECT_MOVE or whatever is allowed by src
  150. ** SHIFT -- DROPEFFECT_MOVE
  151. ** CTRL -- DROPEFFECT_COPY
  152. ** CTRL-SHIFT -- DROPEFFECT_LINK
  153. */
  154. *lpdwEffect = OleStdGetDropEffect(grfKeyState);
  155. if (*lpdwEffect == 0) {
  156. // No modifier keys given. Try in order MOVE, COPY, LINK.
  157. if ((DROPEFFECT_MOVE & dwOKEffects) && lpOleDoc->m_fCanDropCopy)
  158. *lpdwEffect = DROPEFFECT_MOVE;
  159. else if ((DROPEFFECT_COPY & dwOKEffects) && lpOleDoc->m_fCanDropCopy)
  160. *lpdwEffect = DROPEFFECT_COPY;
  161. else if ((DROPEFFECT_LINK & dwOKEffects) && lpOleDoc->m_fCanDropLink)
  162. *lpdwEffect = DROPEFFECT_LINK;
  163. else
  164. goto dropeffect_none;
  165. } else {
  166. /* OLE2NOTE: we should check if the drag source application allows
  167. ** the desired drop effect.
  168. */
  169. if (!(*lpdwEffect & dwOKEffects))
  170. goto dropeffect_none;
  171. if ((*lpdwEffect == DROPEFFECT_COPY || *lpdwEffect == DROPEFFECT_MOVE)
  172. && ! lpOleDoc->m_fCanDropCopy)
  173. goto dropeffect_none;
  174. if (*lpdwEffect == DROPEFFECT_LINK && ! lpOleDoc->m_fCanDropLink)
  175. goto dropeffect_none;
  176. }
  177. *lpdwEffect |= dwScrollEffect;
  178. return TRUE;
  179. dropeffect_none:
  180. *lpdwEffect = DROPEFFECT_NONE;
  181. return FALSE;
  182. }
  183. /* OleDoc_DoDragDrop
  184. * -----------------
  185. * Actually perform a drag/drop operation with the current selection in
  186. * the source document (lpSrcOleDoc).
  187. *
  188. * returns the result effect of the drag/drop operation:
  189. * DROPEFFECT_NONE,
  190. * DROPEFFECT_COPY,
  191. * DROPEFFECT_MOVE, or
  192. * DROPEFFECT_LINK
  193. */
  194. DWORD OleDoc_DoDragDrop (LPOLEDOC lpSrcOleDoc)
  195. {
  196. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  197. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  198. LPOUTLINEDOC lpSrcOutlineDoc = (LPOUTLINEDOC)lpSrcOleDoc;
  199. LPOLEDOC lpDragDoc;
  200. LPLINELIST lpSrcLL =
  201. (LPLINELIST)&((LPOUTLINEDOC)lpSrcOleDoc)->m_LineList;
  202. DWORD dwEffect = 0;
  203. LPLINE lplineStart, lplineEnd;
  204. LINERANGE linerange;
  205. BOOL fPrevEnable1;
  206. BOOL fPrevEnable2;
  207. HRESULT hrErr;
  208. OLEDBG_BEGIN3("OleDoc_DoDragDrop\r\n")
  209. /* squirrel away a copy of the current selection to the ClipboardDoc */
  210. lpDragDoc = (LPOLEDOC)OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc);
  211. if ( ! lpDragDoc) {
  212. dwEffect = DROPEFFECT_NONE;
  213. goto error;
  214. }
  215. /* OLE2NOTE: initially the DataTransferDoc is created with a 0 ref
  216. ** count. in order to have a stable Doc object during the drag/
  217. ** drop operation, we intially AddRef the Doc ref cnt and later
  218. ** Release it. This AddRef is artificial; it is simply
  219. ** done to guarantee that a harmless QueryInterface followed by
  220. ** a Release does not inadvertantly force our object to destroy
  221. ** itself prematurely.
  222. */
  223. OleDoc_AddRef(lpDragDoc);
  224. //NOTE: we need to keep the LPLINE pointers
  225. // rather than the indexes because the
  226. // indexes will not be the same after the
  227. // drop occurs -- the drop adds new
  228. // entries to the list thereby shifting
  229. // the whole list.
  230. LineList_GetSel( lpSrcLL, (LPLINERANGE)&linerange );
  231. lplineStart = LineList_GetLine ( lpSrcLL, linerange.m_nStartLine );
  232. lplineEnd = LineList_GetLine ( lpSrcLL, linerange.m_nEndLine );
  233. if (! lplineStart || ! lplineEnd) {
  234. dwEffect = DROPEFFECT_NONE;
  235. goto error;
  236. }
  237. lpSrcOleDoc->m_fLocalDrop = FALSE;
  238. lpSrcOleDoc->m_fLocalDrag = TRUE;
  239. /* OLE2NOTE: it is VERY important to DISABLE the Busy/NotResponding
  240. ** dialogs BEFORE calling DoDragDrop. The DoDragDrop API starts
  241. ** a mouse capture modal loop. if the Busy/NotResponding comes
  242. ** up in the middle of this loop (eg. if one of the remoted
  243. ** calls like IDropTarget::DragOver call takes a long time, then
  244. ** the NotResponding dialog may want to come up), then the mouse
  245. ** capture is lost by OLE and things can get messed up.
  246. */
  247. OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2);
  248. OLEDBG_BEGIN2("DoDragDrop called\r\n")
  249. hrErr = DoDragDrop ( (LPDATAOBJECT) &lpDragDoc->m_DataObject,
  250. (LPDROPSOURCE) &lpSrcOleDoc->m_DropSource,
  251. DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK,
  252. (LPDWORD) &dwEffect
  253. );
  254. OLEDBG_END2
  255. // re-enable the Busy/NotResponding dialogs
  256. OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2);
  257. #if defined( _DEBUG )
  258. if (FAILED(hrErr))
  259. OleDbgOutHResult("DoDragDrop returned", hrErr);
  260. #endif
  261. lpSrcOleDoc->m_fLocalDrag = FALSE;
  262. /* OLE2NOTE: we need to guard the lifetime of our lpSrcOleDoc
  263. ** object while we are deleting the lines that were drag
  264. ** moved. it is possible that deleting these lines could
  265. ** cause the deletion of a PseudoObj. the deletion of a
  266. ** PseudoObj will cause the Doc to be unlock
  267. ** (CoLockObjectExternal(FALSE,TRUE) called). each PseudoObj
  268. ** holds a strong lock on the Doc. It is always best to have
  269. ** a memory guard around such critical sections of code. in
  270. ** this case, it is particularly important if we were an
  271. ** in-place active server and this drag ended up in a drop
  272. ** in our outer container. this scenario will lead to a
  273. ** crash if we do not hold this memory guard.
  274. */
  275. OleDoc_Lock(lpSrcOleDoc, TRUE, 0);
  276. /* if after the Drag/Drop modal (mouse capture) loop is finished
  277. ** and a drag MOVE operation was performed, then we must delete
  278. ** the lines that were dragged.
  279. */
  280. if ( GetScode(hrErr) == DRAGDROP_S_DROP
  281. && (dwEffect & DROPEFFECT_MOVE) != 0 ) {
  282. int i,j,iEnd;
  283. LPLINE lplineFocusLine;
  284. /* disable repainting and sending data changed notifications
  285. ** until after all lines have been deleted.
  286. */
  287. OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, FALSE );
  288. /* if the drop was local to our document, then we must take
  289. ** into account that the line indices of the original source
  290. ** of the drag could have shifted because the dropped lines
  291. ** have been inserted into our document. thus we will
  292. ** re-determine the source line indices.
  293. */
  294. if (lpSrcOleDoc->m_fLocalDrop) {
  295. i = LineList_GetFocusLineIndex ( lpSrcLL );
  296. lplineFocusLine = LineList_GetLine ( lpSrcLL, i );
  297. }
  298. for ( i = j = LineList_GetLineIndex(lpSrcLL,lplineStart ) ,
  299. iEnd = LineList_GetLineIndex(lpSrcLL,lplineEnd ) ;
  300. i <= iEnd ;
  301. i++
  302. ) OutlineDoc_DeleteLine ((LPOUTLINEDOC)lpSrcOleDoc, j );
  303. LineList_RecalcMaxLineWidthInHimetric(lpSrcLL, 0);
  304. if (lpSrcOleDoc->m_fLocalDrop) {
  305. i = LineList_GetLineIndex ( lpSrcLL, lplineFocusLine );
  306. LineList_SetFocusLine ( lpSrcLL, (WORD)i );
  307. }
  308. OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE );
  309. /* if it is a local Drag/Drop move, we need to balance the
  310. ** SetRedraw(FALSE) call that was made in the implementation
  311. ** of IDropTarget::Drop.
  312. */
  313. if (lpSrcOleDoc->m_fLocalDrop)
  314. OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpSrcOleDoc, TRUE );
  315. LineList_ForceRedraw ( lpSrcLL, FALSE );
  316. }
  317. OleDoc_Release(lpDragDoc); // rel artificial AddRef above
  318. OleDoc_Lock(lpSrcOleDoc, FALSE, FALSE); // unlock artificial lock guard
  319. OLEDBG_END3
  320. return dwEffect;
  321. error:
  322. OLEDBG_END3
  323. return dwEffect;
  324. }
  325. /*************************************************************************
  326. ** OleDoc::IDropSource interface implementation
  327. *************************************************************************/
  328. STDMETHODIMP OleDoc_DropSource_QueryInterface(
  329. LPDROPSOURCE lpThis,
  330. REFIID riid,
  331. LPVOID FAR* lplpvObj
  332. )
  333. {
  334. LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;
  335. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  336. }
  337. STDMETHODIMP_(ULONG) OleDoc_DropSource_AddRef( LPDROPSOURCE lpThis )
  338. {
  339. LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;
  340. OleDbgAddRefMethod(lpThis, "IDropSource");
  341. return OleDoc_AddRef(lpOleDoc);
  342. }
  343. STDMETHODIMP_(ULONG) OleDoc_DropSource_Release ( LPDROPSOURCE lpThis)
  344. {
  345. LPOLEDOC lpOleDoc = ((struct CDocDropSourceImpl FAR*)lpThis)->lpOleDoc;
  346. OleDbgReleaseMethod(lpThis, "IDropSource");
  347. return OleDoc_Release(lpOleDoc);
  348. }
  349. STDMETHODIMP OleDoc_DropSource_QueryContinueDrag (
  350. LPDROPSOURCE lpThis,
  351. BOOL fEscapePressed,
  352. DWORD grfKeyState
  353. ){
  354. if (fEscapePressed)
  355. return ResultFromScode(DRAGDROP_S_CANCEL);
  356. else if (!(grfKeyState & MK_LBUTTON))
  357. return ResultFromScode(DRAGDROP_S_DROP);
  358. else
  359. return NOERROR;
  360. }
  361. STDMETHODIMP OleDoc_DropSource_GiveFeedback (
  362. LPDROPSOURCE lpThis,
  363. DWORD dwEffect
  364. )
  365. {
  366. // Tell OLE to use the standard drag/drop feedback cursors
  367. return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
  368. #if defined( IF_SPECIAL_DD_CURSORS_NEEDED )
  369. switch (dwEffect) {
  370. case DROPEFFECT_NONE:
  371. SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragNone );
  372. break;
  373. case DROPEFFECT_COPY:
  374. SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragCopy );
  375. break;
  376. case DROPEFFECT_MOVE:
  377. SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragMove );
  378. break;
  379. case DROPEFFECT_LINK:
  380. SetCursor ( ((LPOLEAPP)g_lpApp)->m_hcursorDragLink );
  381. break;
  382. }
  383. return NOERROR;
  384. #endif
  385. }
  386. /*************************************************************************
  387. ** OleDoc::IDropTarget interface implementation
  388. *************************************************************************/
  389. STDMETHODIMP OleDoc_DropTarget_QueryInterface(
  390. LPDROPTARGET lpThis,
  391. REFIID riid,
  392. LPVOID FAR* lplpvObj
  393. )
  394. {
  395. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  396. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  397. }
  398. STDMETHODIMP_(ULONG) OleDoc_DropTarget_AddRef(LPDROPTARGET lpThis)
  399. {
  400. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  401. OleDbgAddRefMethod(lpThis, "IDropTarget");
  402. return OleDoc_AddRef(lpOleDoc);
  403. }
  404. STDMETHODIMP_(ULONG) OleDoc_DropTarget_Release ( LPDROPTARGET lpThis)
  405. {
  406. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  407. OleDbgReleaseMethod(lpThis, "IDropTarget");
  408. return OleDoc_Release(lpOleDoc);
  409. }
  410. STDMETHODIMP OleDoc_DropTarget_DragEnter (
  411. LPDROPTARGET lpThis,
  412. LPDATAOBJECT lpDataObj,
  413. DWORD grfKeyState,
  414. POINTL pointl,
  415. LPDWORD lpdwEffect
  416. )
  417. {
  418. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  419. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  420. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  421. BOOL fDragScroll;
  422. OLEDBG_BEGIN2("OleDoc_DropTarget_DragEnter\r\n")
  423. lpOleDoc->m_fDragLeave = FALSE;
  424. lpOleDoc->m_dwTimeEnterScrollArea = 0;
  425. lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL;
  426. /* Determine if the drag source data object offers a data format
  427. ** that we can copy and/or link to.
  428. */
  429. lpOleDoc->m_fCanDropCopy = OleDoc_QueryPasteFromData(
  430. lpOleDoc,
  431. lpDataObj,
  432. FALSE /* fLink */
  433. );
  434. lpOleDoc->m_fCanDropLink = OleDoc_QueryPasteFromData(
  435. lpOleDoc,
  436. lpDataObj,
  437. TRUE /* fLink */
  438. );
  439. fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl );
  440. if (OleDoc_QueryDrop(lpOleDoc,grfKeyState,pointl,fDragScroll,lpdwEffect))
  441. LineList_SetDragOverLineFromPointl( lpLL, pointl );
  442. OLEDBG_END2
  443. return NOERROR;
  444. }
  445. STDMETHODIMP OleDoc_DropTarget_DragOver (
  446. LPDROPTARGET lpThis,
  447. DWORD grfKeyState,
  448. POINTL pointl,
  449. LPDWORD lpdwEffect
  450. )
  451. {
  452. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  453. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  454. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  455. BOOL fDragScroll;
  456. fDragScroll = OleDoc_DoDragScroll ( lpOleDoc, pointl );
  457. if (OleDoc_QueryDrop(lpOleDoc,grfKeyState, pointl,fDragScroll,lpdwEffect))
  458. LineList_SetDragOverLineFromPointl( lpLL, pointl );
  459. else
  460. LineList_RestoreDragFeedback( lpLL );
  461. return NOERROR;
  462. }
  463. STDMETHODIMP OleDoc_DropTarget_DragLeave ( LPDROPTARGET lpThis)
  464. {
  465. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  466. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  467. OLEDBG_BEGIN2("OleDoc_DropTarget_DragLeave\r\n")
  468. lpOleDoc->m_fDragLeave = TRUE;
  469. LineList_RestoreDragFeedback( lpLL );
  470. OLEDBG_END2
  471. return NOERROR;
  472. }
  473. STDMETHODIMP OleDoc_DropTarget_Drop (
  474. LPDROPTARGET lpThis,
  475. LPDATAOBJECT lpDataObj,
  476. DWORD grfKeyState,
  477. POINTL pointl,
  478. LPDWORD lpdwEffect
  479. )
  480. {
  481. LPOLEDOC lpOleDoc = ((struct CDocDropTargetImpl FAR*)lpThis)->lpOleDoc;
  482. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  483. OLEDBG_BEGIN2("OleDoc_DropTarget_Drop\r\n")
  484. lpOleDoc->m_fDragLeave = TRUE;
  485. lpOleDoc->m_fLocalDrop = TRUE;
  486. LineList_RestoreDragFeedback( lpLL );
  487. SetFocus( LineList_GetWindow( lpLL) );
  488. if (OleDoc_QueryDrop(lpOleDoc, grfKeyState, pointl, FALSE, lpdwEffect)) {
  489. BOOL fLink = (*lpdwEffect == DROPEFFECT_LINK);
  490. int iFocusLine = LineList_GetFocusLineIndex( lpLL );
  491. BOOL fStatus;
  492. OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, FALSE );
  493. LineList_SetFocusLineFromPointl ( lpLL, pointl );
  494. fStatus = OleDoc_PasteFromData(
  495. lpOleDoc,
  496. lpDataObj,
  497. lpOleDoc->m_fLocalDrag, /* data source is local to app */
  498. fLink
  499. );
  500. // if drop was unsuccessfull, restore the original focus line
  501. if (! fStatus)
  502. LineList_SetFocusLine( lpLL, (WORD)iFocusLine );
  503. #if defined( INPLACE_CNTR )
  504. {
  505. LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  506. /* OLE2NOTE: if there is currently a UIActive OLE object,
  507. ** then we must tell it to UIDeactivate after
  508. ** the drop has completed.
  509. */
  510. if (lpContainerDoc->m_lpLastUIActiveLine) {
  511. ContainerLine_UIDeactivate(
  512. lpContainerDoc->m_lpLastUIActiveLine);
  513. }
  514. }
  515. #endif
  516. #if defined( INPLACE_SVR )
  517. {
  518. /* OLE2NOTE: if the drop was into a in-place visible
  519. ** (in-place active but NOT UIActive object), then we
  520. ** want to UIActivate the object after the drop is
  521. ** complete.
  522. */
  523. ServerDoc_UIActivate((LPSERVERDOC) lpOleDoc);
  524. }
  525. #endif
  526. /* if it is a local Drag/Drop move, don't enable redraw.
  527. ** after the source is done deleting the moved lines, it
  528. ** will re-enable redraw
  529. */
  530. if (! (lpOleDoc->m_fLocalDrag
  531. && (*lpdwEffect & DROPEFFECT_MOVE) != 0 ))
  532. OutlineDoc_SetRedraw ( (LPOUTLINEDOC)lpOleDoc, TRUE );
  533. }
  534. OLEDBG_END2
  535. return NOERROR;
  536. }
  537. #endif // USE_DRAGDROP