Release 990226.
[wine/multimedia.git] / ole / ole2.c
blob61f909d46df97d0a838f460db42e50f53b337396
1 /*
2 * OLE2 library
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1999 Francis Beaudet
6 */
8 #include <assert.h>
10 #include "windows.h"
11 #include "winerror.h"
12 #include "ole2.h"
13 #include "process.h"
14 #include "debug.h"
15 #include "objbase.h"
16 #include "objidl.h"
17 #include "wine/obj_base.h"
18 #include "wine/obj_clientserver.h"
19 #include "wine/obj_storage.h"
20 #include "wine/obj_moniker.h"
22 /******************************************************************************
23 * These are static/global variables and internal data structures that the
24 * OLE module uses to maintain it's state.
26 typedef struct tagDropTargetNode
28 HWND hwndTarget;
29 IDropTarget* dropTarget;
30 struct tagDropTargetNode* prevDropTarget;
31 struct tagDropTargetNode* nextDropTarget;
32 } DropTargetNode;
34 typedef struct tagTrackerWindowInfo
36 IDataObject* dataObject;
37 IDropSource* dropSource;
38 DWORD dwOKEffect;
39 DWORD* pdwEffect;
40 BOOL trackingDone;
41 HRESULT returnValue;
43 BOOL escPressed;
44 HWND curDragTargetHWND;
45 IDropTarget* curDragTarget;
46 } TrackerWindowInfo;
49 * This is the lock count on the OLE library. It is controlled by the
50 * OLEInitialize/OLEUninitialize methods.
52 static ULONG OLE_moduleLockCount = 0;
55 * Name of our registered window class.
57 static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
60 * This is the head of the Drop target container.
62 static DropTargetNode* targetListHead = NULL;
64 /******************************************************************************
65 * These are the prototypes of the utility methods used for OLE Drag n Drop
67 static void OLEDD_Initialize();
68 static void OLEDD_UnInitialize();
69 static void OLEDD_InsertDropTarget(
70 DropTargetNode* nodeToAdd);
71 static DropTargetNode* OLEDD_ExtractDropTarget(
72 HWND hwndOfTarget);
73 static DropTargetNode* OLEDD_FindDropTarget(
74 HWND hwndOfTarget);
75 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
76 HWND hwnd,
77 UINT uMsg,
78 WPARAM wParam,
79 LPARAM lParam);
80 static void OLEDD_TrackMouseMove(
81 TrackerWindowInfo* trackerInfo,
82 POINT mousePos,
83 DWORD keyState);
84 static void OLEDD_TrackStateChange(
85 TrackerWindowInfo* trackerInfo,
86 POINT mousePos,
87 DWORD keyState);
88 static DWORD OLEDD_GetButtonState();
91 /******************************************************************************
92 * OleBuildVersion [OLE2.1]
94 DWORD WINAPI OleBuildVersion(void)
96 TRACE(ole,"(void)\n");
97 return (rmm<<16)+rup;
100 /***********************************************************************
101 * OleInitialize (OLE2.2) (OLE32.108)
103 HRESULT WINAPI OleInitialize(LPVOID reserved)
105 HRESULT hr;
107 TRACE(ole, "(%p)\n", reserved);
110 * The first duty of the OleInitialize is to initialize the COM libraries.
112 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
115 * If the CoInitializeEx call failed, the OLE libraries can't be
116 * initialized.
118 if (FAILED(hr))
119 return hr;
122 * Then, it has to initialize the OLE specific modules.
123 * This includes:
124 * Clipboard
125 * Drag and Drop
126 * Object linking and Embedding
127 * In-place activation
129 if (OLE_moduleLockCount==0)
132 * Initialize the libraries.
134 TRACE(ole, "() - Initializing the OLE libraries\n");
137 * Drag and Drop
139 OLEDD_Initialize();
143 * Then, we increase the lock count on the OLE module.
145 OLE_moduleLockCount++;
147 return hr;
150 /******************************************************************************
151 * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108]
153 * NOTES
154 * Is DWORD really the correct return type for this function?
156 DWORD WINAPI CoGetCurrentProcess(void) {
157 return (DWORD)PROCESS_Current();
160 /******************************************************************************
161 * OleUninitialize [OLE2.3] [OLE32.131]
163 void WINAPI OleUninitialize(void)
165 TRACE(ole, "()\n");
168 * Decrease the lock count on the OLE module.
170 OLE_moduleLockCount--;
173 * If we hit the bottom of the lock stack, free the libraries.
175 if (OLE_moduleLockCount==0)
178 * Actually free the libraries.
180 TRACE(ole, "() - Freeing the last reference count\n");
183 * Drag and Drop
185 OLEDD_UnInitialize();
189 * Then, uninitialize the COM libraries.
191 CoUninitialize();
194 /***********************************************************************
195 * OleFlushClipboard [OLE2.76]
197 HRESULT WINAPI OleFlushClipboard16(void)
199 return S_OK;
202 /***********************************************************************
203 * OleSetClipboard [OLE32.127]
205 HRESULT WINAPI OleSetClipboard(LPVOID pDataObj)
207 FIXME(ole,"(%p), stub!\n", pDataObj);
208 return S_OK;
211 /******************************************************************************
212 * CoRegisterMessageFilter32 [OLE32.38]
214 HRESULT WINAPI CoRegisterMessageFilter(
215 LPMESSAGEFILTER lpMessageFilter, /* Pointer to interface */
216 LPMESSAGEFILTER *lplpMessageFilter /* Indirect pointer to prior instance if non-NULL */
218 FIXME(ole,"stub\n");
219 if (lplpMessageFilter) {
220 *lplpMessageFilter = NULL;
222 return S_OK;
225 /******************************************************************************
226 * OleInitializeWOW [OLE32.109]
228 HRESULT WINAPI OleInitializeWOW(DWORD x) {
229 FIXME(ole,"(0x%08lx),stub!\n",x);
230 return 0;
233 /***********************************************************************
234 * RegisterDragDrop16 (OLE2.35)
236 HRESULT WINAPI RegisterDragDrop16(
237 HWND16 hwnd,
238 LPDROPTARGET pDropTarget
240 FIXME(ole,"(0x%04x,%p),stub!\n",hwnd,pDropTarget);
241 return S_OK;
244 /***********************************************************************
245 * RegisterDragDrop32 (OLE32.139)
247 HRESULT WINAPI RegisterDragDrop(
248 HWND hwnd,
249 LPDROPTARGET pDropTarget)
251 DropTargetNode* dropTargetInfo;
253 TRACE(ole,"(0x%x,%p)\n", hwnd, pDropTarget);
256 * First, check if the window is already registered.
258 dropTargetInfo = OLEDD_FindDropTarget(hwnd);
260 if (dropTargetInfo!=NULL)
261 return DRAGDROP_E_ALREADYREGISTERED;
264 * If it's not there, we can add it. We first create a node for it.
266 dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
268 if (dropTargetInfo==NULL)
269 return E_OUTOFMEMORY;
271 dropTargetInfo->hwndTarget = hwnd;
272 dropTargetInfo->prevDropTarget = NULL;
273 dropTargetInfo->nextDropTarget = NULL;
276 * Don't forget that this is an interface pointer, need to nail it down since
277 * we keep a copy of it.
279 dropTargetInfo->dropTarget = pDropTarget;
280 IDropTarget_AddRef(dropTargetInfo->dropTarget);
282 OLEDD_InsertDropTarget(dropTargetInfo);
284 return S_OK;
287 /***********************************************************************
288 * RevokeDragDrop16 (OLE2.36)
290 HRESULT WINAPI RevokeDragDrop16(
291 HWND16 hwnd
293 FIXME(ole,"(0x%04x),stub!\n",hwnd);
294 return S_OK;
297 /***********************************************************************
298 * RevokeDragDrop32 (OLE32.141)
300 HRESULT WINAPI RevokeDragDrop(
301 HWND hwnd)
303 DropTargetNode* dropTargetInfo;
305 TRACE(ole,"(0x%x)\n", hwnd);
308 * First, check if the window is already registered.
310 dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
313 * If it ain't in there, it's an error.
315 if (dropTargetInfo==NULL)
316 return DRAGDROP_E_NOTREGISTERED;
319 * If it's in there, clean-up it's used memory and
320 * references
322 IDropTarget_Release(dropTargetInfo->dropTarget);
323 HeapFree(GetProcessHeap(), 0, dropTargetInfo);
325 return S_OK;
328 /***********************************************************************
329 * OleRegGetUserType (OLE32.122)
331 HRESULT WINAPI OleRegGetUserType(
332 REFCLSID clsid,
333 DWORD dwFormOfType,
334 LPOLESTR* pszUserType)
336 FIXME(ole,",stub!\n");
337 return S_OK;
340 /***********************************************************************
341 * DoDragDrop32 [OLE32.65]
343 HRESULT WINAPI DoDragDrop (
344 IDataObject *pDataObject, /* ptr to the data obj */
345 IDropSource* pDropSource, /* ptr to the source obj */
346 DWORD dwOKEffect, /* effects allowed by the source */
347 DWORD *pdwEffect) /* ptr to effects of the source */
349 TrackerWindowInfo trackerInfo;
350 HWND hwndTrackWindow;
351 MSG msg;
353 TRACE(ole,"(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
356 * Setup the drag n drop tracking window.
358 trackerInfo.dataObject = pDataObject;
359 trackerInfo.dropSource = pDropSource;
360 trackerInfo.dwOKEffect = dwOKEffect;
361 trackerInfo.pdwEffect = pdwEffect;
362 trackerInfo.trackingDone = FALSE;
363 trackerInfo.escPressed = FALSE;
364 trackerInfo.curDragTargetHWND = 0;
365 trackerInfo.curDragTarget = 0;
367 hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS,
368 "TrackerWindow",
369 WS_POPUP,
370 CW_USEDEFAULT, CW_USEDEFAULT,
371 CW_USEDEFAULT, CW_USEDEFAULT,
375 (LPVOID)&trackerInfo);
377 if (hwndTrackWindow!=0)
380 * Capture the mouse input
382 SetCapture(hwndTrackWindow);
385 * Pump messages. All mouse input should go the the capture window.
387 while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) )
389 if ( (msg.message >= WM_KEYFIRST) &&
390 (msg.message <= WM_KEYFIRST) )
393 * When keyboard messages are sent to windows on this thread, we
394 * want to ignore notify the drop source that the state changed.
395 * in the case of the Escape key, we also notify the drop source
396 * we give it a special meaning.
398 if ( (msg.message==WM_KEYDOWN) &&
399 (msg.wParam==VK_ESCAPE) )
401 trackerInfo.escPressed = TRUE;
405 * Notify the drop source.
407 OLEDD_TrackStateChange(&trackerInfo,
408 msg.pt,
409 OLEDD_GetButtonState());
411 else
414 * Dispatch the messages only when it's not a keyboard message.
416 DispatchMessageA(&msg);
421 * Destroy the temporary window.
423 DestroyWindow(hwndTrackWindow);
425 return trackerInfo.returnValue;
428 return E_FAIL;
431 /***********************************************************************
432 * OleQueryLinkFromData32 [OLE32.118]
434 HRESULT WINAPI OleQueryLinkFromData32(
435 IDataObject* pSrcDataObject)
437 FIXME(ole,"(%p),stub!\n", pSrcDataObject);
438 return S_OK;
441 /***********************************************************************
442 * OleRegGetMiscStatus32 [OLE32.121]
444 HRESULT WINAPI OleRegGetMiscStatus32(
445 REFCLSID clsid,
446 DWORD dwAspect,
447 DWORD* pdwStatus)
449 FIXME(ole,"(),stub!\n");
450 return REGDB_E_CLASSNOTREG;
453 /***********************************************************************
454 * OleGetClipboard32 [OLE32.105]
456 HRESULT WINAPI OleGetClipboard32(
457 IDataObject** ppDataObj)
459 FIXME(ole,"(%p),stub!\n", ppDataObj);
461 if (ppDataObj)
462 *ppDataObj=0;
464 return E_FAIL;
467 /***********************************************************************
468 * OleCreateMenuDescriptor [OLE32.97]
470 HOLEMENU WINAPI OleCreateMenuDescriptor(
471 HMENU hmenuCombined,
472 LPOLEMENUGROUPWIDTHS lpMenuWidths)
474 FIXME(ole,"(%x,%p),stub!\n", hmenuCombined, lpMenuWidths);
476 return NULL;
479 /***********************************************************************
480 * OleDestroyMenuDescriptor [OLE32.99]
482 void WINAPI OleDestroyMenuDescriptor(
483 HOLEMENU hmenuDescriptor)
485 FIXME(ole,"(%x),stub!\n", (unsigned int)hmenuDescriptor);
488 /***********************************************************************
489 * OleSetMenuDescriptor [OLE32.129]
491 HRESULT WINAPI OleSetMenuDescriptor(
492 HOLEMENU hmenuDescriptor,
493 HWND hwndFrame,
494 HWND hwndActiveObject,
495 LPOLEINPLACEFRAME lpFrame,
496 LPOLEINPLACEACTIVEOBJECT lpActiveObject)
498 FIXME(ole,"(%x, %x, %x, %p, %p),stub!\n",
499 (unsigned int)hmenuDescriptor,
500 hwndFrame,
501 hwndActiveObject,
502 lpFrame,
503 lpActiveObject);
505 return E_FAIL;
508 /***
509 * OLEDD_Initialize()
511 * Initializes the OLE drag and drop data structures.
513 static void OLEDD_Initialize()
515 WNDCLASSA wndClass;
517 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
518 wndClass.style = CS_GLOBALCLASS;
519 wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
520 wndClass.cbClsExtra = 0;
521 wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
522 wndClass.hCursor = 0;
523 wndClass.hbrBackground = 0;
524 wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
526 RegisterClassA (&wndClass);
529 /***
530 * OLEDD_UnInitialize()
532 * Releases the OLE drag and drop data structures.
534 static void OLEDD_UnInitialize()
537 * Simply empty the list.
539 while (targetListHead!=NULL)
541 RevokeDragDrop(targetListHead->hwndTarget);
545 /***
546 * OLEDD_InsertDropTarget()
548 * Insert the target node in the tree.
550 static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
552 DropTargetNode* curNode;
553 DropTargetNode** parentNodeLink;
556 * Iterate the tree to find the insertion point.
558 curNode = targetListHead;
559 parentNodeLink = &targetListHead;
561 while (curNode!=NULL)
563 if (nodeToAdd->hwndTarget<curNode->hwndTarget)
566 * If the node we want to add has a smaller HWND, go left
568 parentNodeLink = &curNode->prevDropTarget;
569 curNode = curNode->prevDropTarget;
571 else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
574 * If the node we want to add has a larger HWND, go right
576 parentNodeLink = &curNode->nextDropTarget;
577 curNode = curNode->nextDropTarget;
579 else
582 * The item was found in the list. It shouldn't have been there
584 assert(FALSE);
585 return;
590 * If we get here, we have found a spot for our item. The parentNodeLink
591 * pointer points to the pointer that we have to modify.
592 * The curNode should be NULL. We just have to establish the link and Voila!
594 assert(curNode==NULL);
595 assert(parentNodeLink!=NULL);
596 assert(*parentNodeLink==NULL);
598 *parentNodeLink=nodeToAdd;
601 /***
602 * OLEDD_ExtractDropTarget()
604 * Removes the target node from the tree.
606 static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget)
608 DropTargetNode* curNode;
609 DropTargetNode** parentNodeLink;
612 * Iterate the tree to find the insertion point.
614 curNode = targetListHead;
615 parentNodeLink = &targetListHead;
617 while (curNode!=NULL)
619 if (hwndOfTarget<curNode->hwndTarget)
622 * If the node we want to add has a smaller HWND, go left
624 parentNodeLink = &curNode->prevDropTarget;
625 curNode = curNode->prevDropTarget;
627 else if (hwndOfTarget>curNode->hwndTarget)
630 * If the node we want to add has a larger HWND, go right
632 parentNodeLink = &curNode->nextDropTarget;
633 curNode = curNode->nextDropTarget;
635 else
638 * The item was found in the list. Detach it from it's parent and
639 * re-insert it's kids in the tree.
641 assert(parentNodeLink!=NULL);
642 assert(*parentNodeLink==curNode);
645 * We arbitrately re-attach the left sub-tree to the parent.
647 *parentNodeLink = curNode->prevDropTarget;
650 * And we re-insert the right subtree
652 if (curNode->nextDropTarget!=NULL)
654 OLEDD_InsertDropTarget(curNode->nextDropTarget);
658 * The node we found is still a valid node once we complete
659 * the unlinking of the kids.
661 curNode->nextDropTarget=NULL;
662 curNode->prevDropTarget=NULL;
664 return curNode;
669 * If we get here, the node is not in the tree
671 return NULL;
674 /***
675 * OLEDD_FindDropTarget()
677 * Finds information about the drop target.
679 static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget)
681 DropTargetNode* curNode;
684 * Iterate the tree to find the HWND value.
686 curNode = targetListHead;
688 while (curNode!=NULL)
690 if (hwndOfTarget<curNode->hwndTarget)
693 * If the node we want to add has a smaller HWND, go left
695 curNode = curNode->prevDropTarget;
697 else if (hwndOfTarget>curNode->hwndTarget)
700 * If the node we want to add has a larger HWND, go right
702 curNode = curNode->nextDropTarget;
704 else
707 * The item was found in the list.
709 return curNode;
714 * If we get here, the item is not in the list
716 return NULL;
719 /***
720 * OLEDD_DragTrackerWindowProc()
722 * This method is the WindowProcedure of the drag n drop tracking
723 * window. During a drag n Drop operation, an invisible window is created
724 * to receive the user input and act upon it. This procedure is in charge
725 * of this behavior.
727 static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
728 HWND hwnd,
729 UINT uMsg,
730 WPARAM wParam,
731 LPARAM lParam)
733 switch (uMsg)
735 case WM_CREATE:
737 LPCREATESTRUCTA createStruct = (LPCREATESTRUCTA)lParam;
739 SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams);
742 break;
744 case WM_MOUSEMOVE:
746 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
747 POINT mousePos;
750 * Get the current mouse position in screen coordinates.
752 mousePos.x = LOWORD(lParam);
753 mousePos.y = HIWORD(lParam);
754 ClientToScreen(hwnd, &mousePos);
757 * Track the movement of the mouse.
759 OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
761 break;
763 case WM_LBUTTONUP:
764 case WM_MBUTTONUP:
765 case WM_RBUTTONUP:
766 case WM_LBUTTONDOWN:
767 case WM_MBUTTONDOWN:
768 case WM_RBUTTONDOWN:
770 TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0);
771 POINT mousePos;
774 * Get the current mouse position in screen coordinates.
776 mousePos.x = LOWORD(lParam);
777 mousePos.y = HIWORD(lParam);
778 ClientToScreen(hwnd, &mousePos);
781 * Notify everyone that the button state changed
782 * TODO: Check if the "escape" key was pressed.
784 OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
786 break;
791 * This is a window proc after all. Let's call the default.
793 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
796 /***
797 * OLEDD_TrackMouseMove()
799 * This method is invoked while a drag and drop operation is in effect.
800 * it will generate the appropriate callbacks in the drop source
801 * and drop target. It will also provide the expected feedback to
802 * the user.
804 * params:
805 * trackerInfo - Pointer to the structure identifying the
806 * drag & drop operation that is currently
807 * active.
808 * mousePos - Current position of the mouse in screen
809 * coordinates.
810 * keyState - Contains the state of the shift keys and the
811 * mouse buttons (MK_LBUTTON and the like)
813 static void OLEDD_TrackMouseMove(
814 TrackerWindowInfo* trackerInfo,
815 POINT mousePos,
816 DWORD keyState)
818 HWND hwndNewTarget = 0;
819 HRESULT hr = S_OK;
822 * Get the handle of the window under the mouse
824 hwndNewTarget = WindowFromPoint(mousePos);
827 * If we are hovering over the same target as before, send the
828 * DragOver notification
830 if ( (trackerInfo->curDragTarget != 0) &&
831 (trackerInfo->curDragTargetHWND==hwndNewTarget) )
833 POINTL mousePosParam;
836 * The documentation tells me that the coordinate should be in the target
837 * window's coordinate space. However, the tests I made tell me the
838 * coordinates should be in screen coordinates.
840 mousePosParam.x = mousePos.x;
841 mousePosParam.y = mousePos.y;
843 IDropTarget_DragOver(trackerInfo->curDragTarget,
844 keyState,
845 mousePosParam,
846 trackerInfo->pdwEffect);
848 else
850 DropTargetNode* newDropTargetNode = 0;
853 * If we changed window, we have to notify our old target and check for
854 * the new one.
856 if (trackerInfo->curDragTarget!=0)
858 IDropTarget_DragLeave(trackerInfo->curDragTarget);
862 * Make sure we're hovering over a window.
864 if (hwndNewTarget!=0)
867 * Find-out if there is a drag target under the mouse
869 newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget);
871 trackerInfo->curDragTargetHWND = hwndNewTarget;
872 trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
875 * If there is, notify it that we just dragged-in
877 if (trackerInfo->curDragTarget!=0)
879 POINTL mousePosParam;
882 * The documentation tells me that the coordinate should be in the target
883 * window's coordinate space. However, the tests I made tell me the
884 * coordinates should be in screen coordinates.
886 mousePosParam.x = mousePos.x;
887 mousePosParam.y = mousePos.y;
889 IDropTarget_DragEnter(trackerInfo->curDragTarget,
890 trackerInfo->dataObject,
891 keyState,
892 mousePosParam,
893 trackerInfo->pdwEffect);
896 else
899 * The mouse is not over a window so we don't track anything.
901 trackerInfo->curDragTargetHWND = 0;
902 trackerInfo->curDragTarget = 0;
907 * Now that we have done that, we have to tell the source to give
908 * us feedback on the work being done by the target. If we don't
909 * have a target, simulate no effect.
911 if (trackerInfo->curDragTarget==0)
913 *trackerInfo->pdwEffect = DROPEFFECT_NONE;
916 hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
917 *trackerInfo->pdwEffect);
920 * When we ask for feedback from the drop source, sometimes it will
921 * do all the necessary work and sometimes it will not handle it
922 * when that's the case, we must display the standard drag and drop
923 * cursors.
925 if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
927 if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) ||
928 (*trackerInfo->pdwEffect & DROPEFFECT_COPY) ||
929 (*trackerInfo->pdwEffect & DROPEFFECT_LINK) )
931 SetCursor(LoadCursorA(0, IDC_SIZEALLA));
933 else
935 SetCursor(LoadCursorA(0, IDC_NOA));
940 /***
941 * OLEDD_TrackStateChange()
943 * This method is invoked while a drag and drop operation is in effect.
944 * It is used to notify the drop target/drop source callbacks when
945 * the state of the keyboard or mouse button change.
947 * params:
948 * trackerInfo - Pointer to the structure identifying the
949 * drag & drop operation that is currently
950 * active.
951 * mousePos - Current position of the mouse in screen
952 * coordinates.
953 * keyState - Contains the state of the shift keys and the
954 * mouse buttons (MK_LBUTTON and the like)
956 static void OLEDD_TrackStateChange(
957 TrackerWindowInfo* trackerInfo,
958 POINT mousePos,
959 DWORD keyState)
962 * Ask the drop source what to do with the operation.
964 trackerInfo->returnValue = IDropSource_QueryContinueDrag(
965 trackerInfo->dropSource,
966 trackerInfo->escPressed,
967 keyState);
970 * All the return valued will stop the operation except the S_OK
971 * return value.
973 if (trackerInfo->returnValue!=S_OK)
976 * Make sure the message loop in DoDragDrop stops
978 trackerInfo->trackingDone = TRUE;
981 * Release the mouse in case the drop target decides to show a popup
982 * or a menu or something.
984 ReleaseCapture();
987 * If we end-up over a target, drop the object in the target or
988 * inform the target that the operation was cancelled.
990 if (trackerInfo->curDragTarget!=0)
992 switch (trackerInfo->returnValue)
995 * If the source wants us to complete the operation, we tell
996 * the drop target that we just dropped the object in it.
998 case DRAGDROP_S_DROP:
1000 POINTL mousePosParam;
1003 * The documentation tells me that the coordinate should be
1004 * in the target window's coordinate space. However, the tests
1005 * I made tell me the coordinates should be in screen coordinates.
1007 mousePosParam.x = mousePos.x;
1008 mousePosParam.y = mousePos.y;
1010 IDropTarget_Drop(trackerInfo->curDragTarget,
1011 trackerInfo->dataObject,
1012 keyState,
1013 mousePosParam,
1014 trackerInfo->pdwEffect);
1015 break;
1018 * If the source told us that we should cancel, fool the drop
1019 * target by telling it that the mouse left it's window.
1021 case DRAGDROP_S_CANCEL:
1022 IDropTarget_DragLeave(trackerInfo->curDragTarget);
1023 break;
1029 /***
1030 * OLEDD_GetButtonState()
1032 * This method will use the current state of the keyboard to build
1033 * a button state mask equivalent to the one passed in the
1034 * WM_MOUSEMOVE wParam.
1036 static DWORD OLEDD_GetButtonState()
1038 BYTE keyboardState[256];
1039 DWORD keyMask = 0;
1041 GetKeyboardState(keyboardState);
1043 if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
1044 keyMask |= MK_SHIFT;
1046 if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
1047 keyMask |= MK_CONTROL;
1049 if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
1050 keyMask |= MK_LBUTTON;
1052 if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
1053 keyMask |= MK_RBUTTON;
1055 if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
1056 keyMask |= MK_MBUTTON;
1058 return keyMask;