Implemented the OLE Drag and Drop target registration mechanism and

the DoDragDrop loop to perform the DnD operation.
oldstable
Francis Beaudet 1999-02-13 09:13:49 +00:00 committed by Alexandre Julliard
parent 197a8e163e
commit 3f7ad7aa98
11 changed files with 945 additions and 44 deletions

View File

@ -198,7 +198,7 @@ static char **OBM_Icons_Data[OIC_LAST-OIC_FIRST+1] =
#define OCR_BASE1 (OCR_BASE0 + OCR_LAST0 - OCR_FIRST0 + 1)
#define OCR_FIRST2 OCR_SIZE
#define OCR_LAST2 OCR_SIZENS
#define OCR_LAST2 OCR_SIZEALL
#define OCR_BASE2 (OCR_BASE1 + OCR_LAST1 - OCR_FIRST1 + 1)
#define OCR_FIRST3 OCR_NO
@ -229,8 +229,8 @@ static char **OBM_Cursors_Data[NB_CURSORS] =
ocr_sizenesw, /* OCR_SIZENESW */
ocr_sizewe, /* OCR_SIZEWE */
ocr_sizens, /* OCR_SIZENS */
ocr_size, /* OCR_SIZEALL */ /* Re-used the same one as OCR_SIZE for now */
#if 0
ocr_sizeall, /* OCR_SIZEALL */
ocr_icocur /* OCR_ICOCUR */
#endif
ocr_no, /* OCR_NO */

View File

@ -5,13 +5,9 @@
#ifndef __WINE_OLE2_H
#define __WINE_OLE2_H
#include "oleidl.h"
#include "wintypes.h"
/* to be implemented */
/* FIXME: this should be defined somewhere in oleidl.h instead, should it be repeated here ? */
typedef LPVOID LPDROPTARGET;
/* OLE version */
#define rmm 23
#define rup 639
@ -27,11 +23,23 @@ typedef struct tagOleMenuGroupWidths *LPOLEMENUGROUPWIDTHS32;
typedef HGLOBAL32 HOLEMENU32;
HRESULT WINAPI RegisterDragDrop16(HWND16,LPVOID);
HRESULT WINAPI RegisterDragDrop32(HWND32,LPVOID);
/*
* API declarations
*/
HRESULT WINAPI RegisterDragDrop16(HWND16,LPDROPTARGET);
HRESULT WINAPI RegisterDragDrop32(HWND32,LPDROPTARGET);
#define RegisterDragDrop WINELIB_NAME(RegisterDragDrop)
HRESULT WINAPI RevokeDragDrop16(HWND16);
HRESULT WINAPI RevokeDragDrop32(HWND32);
#define RevokeDragDrop WINELIB_NAME(RevokeDragDrop)
HRESULT WINAPI DoDragDrop16(LPDATAOBJECT,
LPDROPSOURCE,
DWORD,
DWORD*);
HRESULT WINAPI DoDragDrop32(LPDATAOBJECT,
LPDROPSOURCE,
DWORD,
DWORD*);
#define DoDragDrop WINELIB_NAME(DoDragDrop)
#endif /* __WINE_OLE2_H */

21
include/oleidl.h 100644
View File

@ -0,0 +1,21 @@
#ifndef __WINE_OLEIDL_H
#define __WINE_OLEIDL_H
#include "wine/obj_base.h"
/* the following depend only on obj_base.h */
#include "wine/obj_storage.h"
/* the following depend on obj_storage.h */
#include "wine/obj_moniker.h"
/* the following depend on obj_moniker */
#include "wine/obj_dataobject.h"
/* the following depend on obj_dataobject.h */
#include "wine/obj_dragdrop.h"
#endif /* __WINE_OLEIDL_H */

View File

@ -50,7 +50,5 @@ DEFINE_GUID (IID_IDockingWindowFrame, 0x47D2657AL, 0x7B27, 0x11D0, 0x8C, 0xA9, 0
DEFINE_GUID (IID_MyComputer, 0x20D04FE0L, 0x3AEA, 0x1069, 0xA2, 0xD8, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D);
DEFINE_SHLGUID(IID_IEnumOLEVERB, 0x00000104L, 0, 0);
DEFINE_SHLGUID(IID_IViewObject, 0x0000010DL, 0, 0);
DEFINE_SHLGUID(IID_IDropSource, 0x00000121L, 0, 0);
DEFINE_SHLGUID(IID_IDropTarget, 0x00000122L, 0, 0);
#endif /* __WINE_SHLGUID_H */

View File

@ -389,13 +389,6 @@ typedef enum tagSHCONTF
SHCONTF_INCLUDEHIDDEN = 128 /* for hidden/system objects */
} SHCONTF;
/* from oleidl.h */
#define DROPEFFECT_NONE 0
#define DROPEFFECT_COPY 1
#define DROPEFFECT_MOVE 2
#define DROPEFFECT_LINK 4
#define DROPEFFECT_SCROLL 0x80000000
/* IShellFolder::GetAttributesOf flags */
#define SFGAO_CANCOPY DROPEFFECT_COPY /* Objects can be copied */
#define SFGAO_CANMOVE DROPEFFECT_MOVE /* Objects can be moved */

View File

@ -28,4 +28,15 @@
#pragma pack(4)
/*
* POINTL structure. Used in some OLE calls.
*/
typedef struct _POINTL
{
LONG x;
LONG y;
} POINTL;
#endif /* __INCLUDE_WINDEF_H */

View File

@ -0,0 +1,80 @@
/*
* Defines the COM interfaces and APIs related to OLE Drag and Drop.
*
* Depends on 'obj_base.h'.
*/
#ifndef __WINE_WINE_OBJ_DRAGDROP_H
#define __WINE_WINE_OBJ_DRAGDROP_H
#include "winnt.h"
#include "windef.h"
/*****************************************************************************
* Predeclare the interfaces
*/
DEFINE_OLEGUID(IID_IDropSource, 0x00000121L, 0, 0);
typedef struct IDropSource IDropSource,*LPDROPSOURCE;
DEFINE_OLEGUID(IID_IDropTarget, 0x00000122L, 0, 0);
typedef struct IDropTarget IDropTarget,*LPDROPTARGET;
/*****************************************************************************
* DROPEFFECT enumeration
*/
#define DROPEFFECT_NONE 0
#define DROPEFFECT_COPY 1
#define DROPEFFECT_MOVE 2
#define DROPEFFECT_LINK 4
#define DROPEFFECT_SCROLL 0x80000000
/*****************************************************************************
* IDropSource interface
*/
#define ICOM_INTERFACE IDropSource
ICOM_BEGIN(IDropSource,IUnknown)
ICOM_METHOD2(HRESULT, QueryContinueDrag, BOOL32, fEscapePressed, DWORD, grfKeyState);
ICOM_METHOD1(HRESULT, GiveFeedback, DWORD, dwEffect);
ICOM_END(IDropSource)
#undef ICOM_INTERFACE
#if !defined(__cplusplus) || defined(CINTERFACE)
/*** IUnknown methods ***/
#define IDropSource_QueryInterface(p,a,b) ICOM_ICALL2(IUnknown,QueryInterface,p,a,b)
#define IDropSource_AddRef(p) ICOM_ICALL (IUnknown,AddRef,p)
#define IDropSource_Release(p) ICOM_ICALL (IUnknown,Release,p)
/*** IDropTarget methods ***/
#define IDropSource_QueryContinueDrag(p,a,b) ICOM_CALL2(QueryContinueDrag,p,a,b)
#define IDropSource_GiveFeedback(p,a) ICOM_CALL1(GiveFeedback,p,a)
#endif
/*****************************************************************************
* IDropTarget interface
*/
#define ICOM_INTERFACE IDropTarget
ICOM_BEGIN(IDropTarget,IUnknown)
ICOM_METHOD4(HRESULT, DragEnter, IDataObject*, pDataObjhect, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect);
ICOM_METHOD3(HRESULT, DragOver, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect);
ICOM_METHOD(HRESULT, DragLeave);
ICOM_METHOD4(HRESULT, Drop, IDataObject*, pDataObjhect, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect);
ICOM_END(IDropTarget)
#undef ICOM_INTERFACE
#if !defined(__cplusplus) || defined(CINTERFACE)
/*** IUnknown methods ***/
#define IDropTarget_QueryInterface(p,a,b) ICOM_ICALL2(IUnknown,QueryInterface,p,a,b)
#define IDropTarget_AddRef(p) ICOM_ICALL (IUnknown,AddRef,p)
#define IDropTarget_Release(p) ICOM_ICALL (IUnknown,Release,p)
/*** IDropTarget methods ***/
#define IDropTarget_DragEnter(p,a,b,c,d) ICOM_CALL4(DragEnter,p,a,b,c,d)
#define IDropTarget_DragOver(p,a,b,c) ICOM_CALL3(DragOver,p,a,b,c)
#define IDropTarget_DragLeave(p) ICOM_CALL(DragLeave,p)
#define IDropTarget_Drop(p,a,b,c,d) ICOM_CALL4(Drop,p,a,b,c,d)
#endif
#endif /* __WINE_WINE_OBJ_DRAGDROP_H */

View File

@ -264,6 +264,9 @@ extern int WIN32_LastError;
/* Drag and Drop */
#define DRAGDROP_S_DROP 0x00040100L
#define DRAGDROP_S_CANCEL 0x00040101L
#define DRAGDROP_E_NOTREGISTERED 0x80040100L
#define DRAGDROP_E_ALREADYREGISTERED 0x80040101L
#define DRAGDROP_S_USEDEFAULTCURSORS 0x00040102L
#define E_UNEXPECTED 0x8000FFFF
@ -290,6 +293,7 @@ extern int WIN32_LastError;
#define CO_E_OBJISREG 0x800401FB
#define OLE_E_ENUM_NOMORE 0x80040002
#define OLE_S_USEREG 0x00040000
#define CLASS_E_NOAGGREGATION 0x80040110
#define CLASS_E_CLASSNOTAVAILABLE 0x80040111
#define E_ACCESSDENIED 0x80070005

View File

@ -485,13 +485,6 @@ DECL_WINELIB_TYPE(POINT)
DECL_WINELIB_TYPE(PPOINT)
DECL_WINELIB_TYPE(LPPOINT)
typedef struct tagPOINTL
{
LONG x;
LONG y;
} POINTL, *PPOINTL, *LPPOINTL;
#define CONV_POINT16TO32(p16,p32) \
((p32)->x = (INT32)(p16)->x, (p32)->y = (INT32)(p16)->y)
#define CONV_POINT32TO16(p32,p16) \

View File

@ -2,8 +2,11 @@
* OLE2 library
*
* Copyright 1995 Martin von Loewis
* Copyright 1999 Francis Beaudet
*/
#include <assert.h>
#include "windows.h"
#include "winerror.h"
#include "ole2.h"
@ -17,15 +20,73 @@
#include "wine/obj_moniker.h"
/******************************************************************************
* These are static/global variables that the OLE module uses to maintain
* it's state.
* These are static/global variables and internal data structures that the
* OLE module uses to maintain it's state.
*/
typedef struct tagDropTargetNode
{
HWND32 hwndTarget;
IDropTarget* dropTarget;
struct tagDropTargetNode* prevDropTarget;
struct tagDropTargetNode* nextDropTarget;
} DropTargetNode;
typedef struct tagTrackerWindowInfo
{
IDataObject* dataObject;
IDropSource* dropSource;
DWORD dwOKEffect;
DWORD* pdwEffect;
BOOL32 trackingDone;
HRESULT returnValue;
BOOL32 escPressed;
HWND32 curDragTargetHWND;
IDropTarget* curDragTarget;
} TrackerWindowInfo;
/*
* This is the lock count on the OLE library. It is controlled by the
* OLEInitialize/OLEUninitialize methods.
*/
static ULONG s_OLEModuleLockCount = 0;
static ULONG OLE_moduleLockCount = 0;
/*
* Name of our registered window class.
*/
static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
/*
* This is the head of the Drop target container.
*/
static DropTargetNode* targetListHead = NULL;
/******************************************************************************
* These are the prototypes of the utility methods used for OLE Drag n Drop
*/
static void OLEDD_Initialize();
static void OLEDD_UnInitialize();
static void OLEDD_InsertDropTarget(
DropTargetNode* nodeToAdd);
static DropTargetNode* OLEDD_ExtractDropTarget(
HWND32 hwndOfTarget);
static DropTargetNode* OLEDD_FindDropTarget(
HWND32 hwndOfTarget);
static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
HWND32 hwnd,
UINT32 uMsg,
WPARAM32 wParam,
LPARAM lParam);
static void OLEDD_TrackMouseMove(
TrackerWindowInfo* trackerInfo,
POINT32 mousePos,
DWORD keyState);
static void OLEDD_TrackStateChange(
TrackerWindowInfo* trackerInfo,
POINT32 mousePos,
DWORD keyState);
static DWORD OLEDD_GetButtonState();
/******************************************************************************
* OleBuildVersion [OLE2.1]
@ -65,18 +126,23 @@ HRESULT WINAPI OleInitialize(LPVOID reserved)
* Object linking and Embedding
* In-place activation
*/
if (s_OLEModuleLockCount==0)
if (OLE_moduleLockCount==0)
{
/*
* Initialize the libraries.
*/
TRACE(ole, "() - Initializing the OLE libraries\n");
/*
* Drag and Drop
*/
OLEDD_Initialize();
}
/*
* Then, we increase the lock count on the OLE module.
*/
s_OLEModuleLockCount++;
OLE_moduleLockCount++;
return hr;
}
@ -101,17 +167,22 @@ void WINAPI OleUninitialize(void)
/*
* Decrease the lock count on the OLE module.
*/
s_OLEModuleLockCount--;
OLE_moduleLockCount--;
/*
* If we hit the bottom of the lock stack, free the libraries.
*/
if (s_OLEModuleLockCount==0)
if (OLE_moduleLockCount==0)
{
/*
* Actually free the libraries.
*/
TRACE(ole, "() - Freeing the last reference count\n");
/*
* Drag and Drop
*/
OLEDD_UnInitialize();
}
/*
@ -175,9 +246,41 @@ HRESULT WINAPI RegisterDragDrop16(
*/
HRESULT WINAPI RegisterDragDrop32(
HWND32 hwnd,
LPDROPTARGET pDropTarget
) {
FIXME(ole,"(0x%04x,%p),stub!\n",hwnd,pDropTarget);
LPDROPTARGET pDropTarget)
{
DropTargetNode* dropTargetInfo;
TRACE(ole,"(0x%x,%p)\n", hwnd, pDropTarget);
/*
* First, check if the window is already registered.
*/
dropTargetInfo = OLEDD_FindDropTarget(hwnd);
if (dropTargetInfo!=NULL)
return DRAGDROP_E_ALREADYREGISTERED;
/*
* If it's not there, we can add it. We first create a node for it.
*/
dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode));
if (dropTargetInfo==NULL)
return E_OUTOFMEMORY;
dropTargetInfo->hwndTarget = hwnd;
dropTargetInfo->prevDropTarget = NULL;
dropTargetInfo->nextDropTarget = NULL;
/*
* Don't forget that this is an interface pointer, need to nail it down since
* we keep a copy of it.
*/
dropTargetInfo->dropTarget = pDropTarget;
IDropTarget_AddRef(dropTargetInfo->dropTarget);
OLEDD_InsertDropTarget(dropTargetInfo);
return S_OK;
}
@ -195,9 +298,30 @@ HRESULT WINAPI RevokeDragDrop16(
* RevokeDragDrop32 (OLE32.141)
*/
HRESULT WINAPI RevokeDragDrop32(
HWND32 hwnd
) {
FIXME(ole,"(0x%04x),stub!\n",hwnd);
HWND32 hwnd)
{
DropTargetNode* dropTargetInfo;
TRACE(ole,"(0x%x)\n", hwnd);
/*
* First, check if the window is already registered.
*/
dropTargetInfo = OLEDD_ExtractDropTarget(hwnd);
/*
* If it ain't in there, it's an error.
*/
if (dropTargetInfo==NULL)
return DRAGDROP_E_NOTREGISTERED;
/*
* If it's in there, clean-up it's used memory and
* references
*/
IDropTarget_Release(dropTargetInfo->dropTarget);
HeapFree(GetProcessHeap(), 0, dropTargetInfo);
return S_OK;
}
@ -218,10 +342,679 @@ HRESULT WINAPI OleRegGetUserType32(
*/
HRESULT WINAPI DoDragDrop32 (
IDataObject *pDataObject, /* ptr to the data obj */
IDataObject *pDropSource, /* ptr to the source obj */
IDropSource* pDropSource, /* ptr to the source obj */
DWORD dwOKEffect, /* effects allowed by the source */
DWORD *pdwEffect) /* ptr to effects of the source */
{
FIXME(ole,"(DataObject %p, DropSource %p): stub!\n", pDataObject, pDropSource);
return DRAGDROP_S_DROP;
TrackerWindowInfo trackerInfo;
HWND32 hwndTrackWindow;
MSG32 msg;
TRACE(ole,"(DataObject %p, DropSource %p)\n", pDataObject, pDropSource);
/*
* Setup the drag n drop tracking window.
*/
trackerInfo.dataObject = pDataObject;
trackerInfo.dropSource = pDropSource;
trackerInfo.dwOKEffect = dwOKEffect;
trackerInfo.pdwEffect = pdwEffect;
trackerInfo.trackingDone = FALSE;
trackerInfo.escPressed = FALSE;
trackerInfo.curDragTargetHWND = 0;
trackerInfo.curDragTarget = 0;
hwndTrackWindow = CreateWindow32A(OLEDD_DRAGTRACKERCLASS,
"TrackerWindow",
WS_POPUP,
CW_USEDEFAULT32, CW_USEDEFAULT32,
CW_USEDEFAULT32, CW_USEDEFAULT32,
0,
0,
0,
(LPVOID)&trackerInfo);
if (hwndTrackWindow!=0)
{
/*
* Capture the mouse input
*/
SetCapture32(hwndTrackWindow);
/*
* Pump messages. All mouse input should go the the capture window.
*/
while (!trackerInfo.trackingDone && GetMessage32A(&msg, 0, 0, 0) )
{
if ( (msg.message >= WM_KEYFIRST) &&
(msg.message <= WM_KEYFIRST) )
{
/*
* When keyboard messages are sent to windows on this thread, we
* want to ignore notify the drop source that the state changed.
* in the case of the Escape key, we also notify the drop source
* we give it a special meaning.
*/
if ( (msg.message==WM_KEYDOWN) &&
(msg.wParam==VK_ESCAPE) )
{
trackerInfo.escPressed = TRUE;
}
/*
* Notify the drop source.
*/
OLEDD_TrackStateChange(&trackerInfo,
msg.pt,
OLEDD_GetButtonState());
}
else
{
/*
* Dispatch the messages only when it's not a keyboard message.
*/
DispatchMessage32A(&msg);
}
}
/*
* Destroy the temporary window.
*/
DestroyWindow32(hwndTrackWindow);
return trackerInfo.returnValue;
}
return E_FAIL;
}
/***********************************************************************
* OleQueryLinkFromData32 [OLE32.118]
*/
HRESULT WINAPI OleQueryLinkFromData32(
IDataObject* pSrcDataObject)
{
FIXME(ole,"(%p),stub!\n", pSrcDataObject);
return S_OK;
}
/***********************************************************************
* OleRegGetMiscStatus32 [OLE32.121]
*/
HRESULT WINAPI OleRegGetMiscStatus32(
REFCLSID clsid,
DWORD dwAspect,
DWORD* pdwStatus)
{
FIXME(ole,"(),stub!\n");
return REGDB_E_CLASSNOTREG;
}
/***********************************************************************
* OleGetClipboard32 [OLE32.105]
*/
HRESULT WINAPI OleGetClipboard32(
IDataObject** ppDataObj)
{
FIXME(ole,"(%p),stub!\n", ppDataObj);
if (ppDataObj)
*ppDataObj=0;
return E_FAIL;
}
/***
* OLEDD_Initialize()
*
* Initializes the OLE drag and drop data structures.
*/
static void OLEDD_Initialize()
{
WNDCLASS32A wndClass;
ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
wndClass.style = CS_GLOBALCLASS;
wndClass.lpfnWndProc = (WNDPROC32)OLEDD_DragTrackerWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
wndClass.hCursor = 0;
wndClass.hbrBackground = 0;
wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS;
RegisterClass32A (&wndClass);
}
/***
* OLEDD_UnInitialize()
*
* Releases the OLE drag and drop data structures.
*/
static void OLEDD_UnInitialize()
{
/*
* Simply empty the list.
*/
while (targetListHead!=NULL)
{
RevokeDragDrop32(targetListHead->hwndTarget);
}
}
/***
* OLEDD_InsertDropTarget()
*
* Insert the target node in the tree.
*/
static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd)
{
DropTargetNode* curNode;
DropTargetNode** parentNodeLink;
/*
* Iterate the tree to find the insertion point.
*/
curNode = targetListHead;
parentNodeLink = &targetListHead;
while (curNode!=NULL)
{
if (nodeToAdd->hwndTarget<curNode->hwndTarget)
{
/*
* If the node we want to add has a smaller HWND, go left
*/
parentNodeLink = &curNode->prevDropTarget;
curNode = curNode->prevDropTarget;
}
else if (nodeToAdd->hwndTarget>curNode->hwndTarget)
{
/*
* If the node we want to add has a larger HWND, go right
*/
parentNodeLink = &curNode->nextDropTarget;
curNode = curNode->nextDropTarget;
}
else
{
/*
* The item was found in the list. It shouldn't have been there
*/
assert(FALSE);
return;
}
}
/*
* If we get here, we have found a spot for our item. The parentNodeLink
* pointer points to the pointer that we have to modify.
* The curNode should be NULL. We just have to establish the link and Voila!
*/
assert(curNode==NULL);
assert(parentNodeLink!=NULL);
assert(*parentNodeLink==NULL);
*parentNodeLink=nodeToAdd;
}
/***
* OLEDD_ExtractDropTarget()
*
* Removes the target node from the tree.
*/
static DropTargetNode* OLEDD_ExtractDropTarget(HWND32 hwndOfTarget)
{
DropTargetNode* curNode;
DropTargetNode** parentNodeLink;
/*
* Iterate the tree to find the insertion point.
*/
curNode = targetListHead;
parentNodeLink = &targetListHead;
while (curNode!=NULL)
{
if (hwndOfTarget<curNode->hwndTarget)
{
/*
* If the node we want to add has a smaller HWND, go left
*/
parentNodeLink = &curNode->prevDropTarget;
curNode = curNode->prevDropTarget;
}
else if (hwndOfTarget>curNode->hwndTarget)
{
/*
* If the node we want to add has a larger HWND, go right
*/
parentNodeLink = &curNode->nextDropTarget;
curNode = curNode->nextDropTarget;
}
else
{
/*
* The item was found in the list. Detach it from it's parent and
* re-insert it's kids in the tree.
*/
assert(parentNodeLink!=NULL);
assert(*parentNodeLink==curNode);
/*
* We arbitrately re-attach the left sub-tree to the parent.
*/
*parentNodeLink = curNode->prevDropTarget;
/*
* And we re-insert the right subtree
*/
if (curNode->nextDropTarget!=NULL)
{
OLEDD_InsertDropTarget(curNode->nextDropTarget);
}
/*
* The node we found is still a valid node once we complete
* the unlinking of the kids.
*/
curNode->nextDropTarget=NULL;
curNode->prevDropTarget=NULL;
return curNode;
}
}
/*
* If we get here, the node is not in the tree
*/
return NULL;
}
/***
* OLEDD_FindDropTarget()
*
* Finds information about the drop target.
*/
static DropTargetNode* OLEDD_FindDropTarget(HWND32 hwndOfTarget)
{
DropTargetNode* curNode;
/*
* Iterate the tree to find the HWND value.
*/
curNode = targetListHead;
while (curNode!=NULL)
{
if (hwndOfTarget<curNode->hwndTarget)
{
/*
* If the node we want to add has a smaller HWND, go left
*/
curNode = curNode->prevDropTarget;
}
else if (hwndOfTarget>curNode->hwndTarget)
{
/*
* If the node we want to add has a larger HWND, go right
*/
curNode = curNode->nextDropTarget;
}
else
{
/*
* The item was found in the list.
*/
return curNode;
}
}
/*
* If we get here, the item is not in the list
*/
return NULL;
}
/***
* OLEDD_DragTrackerWindowProc()
*
* This method is the WindowProcedure of the drag n drop tracking
* window. During a drag n Drop operation, an invisible window is created
* to receive the user input and act upon it. This procedure is in charge
* of this behavior.
*/
static LRESULT WINAPI OLEDD_DragTrackerWindowProc(
HWND32 hwnd,
UINT32 uMsg,
WPARAM32 wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
LPCREATESTRUCT32A createStruct = (LPCREATESTRUCT32A)lParam;
SetWindowLong32A(hwnd, 0, (LONG)createStruct->lpCreateParams);
break;
}
case WM_MOUSEMOVE:
{
TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLong32A(hwnd, 0);
POINT32 mousePos;
/*
* Get the current mouse position in screen coordinates.
*/
mousePos.x = LOWORD(lParam);
mousePos.y = HIWORD(lParam);
ClientToScreen32(hwnd, &mousePos);
/*
* Track the movement of the mouse.
*/
OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam);
break;
}
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
{
TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLong32A(hwnd, 0);
POINT32 mousePos;
/*
* Get the current mouse position in screen coordinates.
*/
mousePos.x = LOWORD(lParam);
mousePos.y = HIWORD(lParam);
ClientToScreen32(hwnd, &mousePos);
/*
* Notify everyone that the button state changed
* TODO: Check if the "escape" key was pressed.
*/
OLEDD_TrackStateChange(trackerInfo, mousePos, wParam);
break;
}
}
/*
* This is a window proc after all. Let's call the default.
*/
return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
}
/***
* OLEDD_TrackMouseMove()
*
* This method is invoked while a drag and drop operation is in effect.
* it will generate the appropriate callbacks in the drop source
* and drop target. It will also provide the expected feedback to
* the user.
*
* params:
* trackerInfo - Pointer to the structure identifying the
* drag & drop operation that is currently
* active.
* mousePos - Current position of the mouse in screen
* coordinates.
* keyState - Contains the state of the shift keys and the
* mouse buttons (MK_LBUTTON and the like)
*/
static void OLEDD_TrackMouseMove(
TrackerWindowInfo* trackerInfo,
POINT32 mousePos,
DWORD keyState)
{
HWND32 hwndNewTarget = 0;
HRESULT hr = S_OK;
/*
* Get the handle of the window under the mouse
*/
hwndNewTarget = WindowFromPoint32(mousePos);
/*
* If we are hovering over the same target as before, send the
* DragOver notification
*/
if ( (trackerInfo->curDragTarget != 0) &&
(trackerInfo->curDragTargetHWND==hwndNewTarget) )
{
POINTL mousePosParam;
/*
* The documentation tells me that the coordinate should be in the target
* window's coordinate space. However, the tests I made tell me the
* coordinates should be in screen coordinates.
*/
mousePosParam.x = mousePos.x;
mousePosParam.y = mousePos.y;
IDropTarget_DragOver(trackerInfo->curDragTarget,
keyState,
mousePosParam,
trackerInfo->pdwEffect);
}
else
{
DropTargetNode* newDropTargetNode = 0;
/*
* If we changed window, we have to notify our old target and check for
* the new one.
*/
if (trackerInfo->curDragTarget!=0)
{
IDropTarget_DragLeave(trackerInfo->curDragTarget);
}
/*
* Make sure we're hovering over a window.
*/
if (hwndNewTarget!=0)
{
/*
* Find-out if there is a drag target under the mouse
*/
newDropTargetNode = OLEDD_FindDropTarget(hwndNewTarget);
trackerInfo->curDragTargetHWND = hwndNewTarget;
trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0;
/*
* If there is, notify it that we just dragged-in
*/
if (trackerInfo->curDragTarget!=0)
{
POINTL mousePosParam;
/*
* The documentation tells me that the coordinate should be in the target
* window's coordinate space. However, the tests I made tell me the
* coordinates should be in screen coordinates.
*/
mousePosParam.x = mousePos.x;
mousePosParam.y = mousePos.y;
IDropTarget_DragEnter(trackerInfo->curDragTarget,
trackerInfo->dataObject,
keyState,
mousePosParam,
trackerInfo->pdwEffect);
}
}
else
{
/*
* The mouse is not over a window so we don't track anything.
*/
trackerInfo->curDragTargetHWND = 0;
trackerInfo->curDragTarget = 0;
}
}
/*
* Now that we have done that, we have to tell the source to give
* us feedback on the work being done by the target. If we don't
* have a target, simulate no effect.
*/
if (trackerInfo->curDragTarget==0)
{
*trackerInfo->pdwEffect = DROPEFFECT_NONE;
}
hr = IDropSource_GiveFeedback(trackerInfo->dropSource,
*trackerInfo->pdwEffect);
/*
* When we ask for feedback from the drop source, sometimes it will
* do all the necessary work and sometimes it will not handle it
* when that's the case, we must display the standard drag and drop
* cursors.
*/
if (hr==DRAGDROP_S_USEDEFAULTCURSORS)
{
if ( (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) ||
(*trackerInfo->pdwEffect & DROPEFFECT_COPY) ||
(*trackerInfo->pdwEffect & DROPEFFECT_LINK) )
{
SetCursor32(LoadCursor32A(0, IDC_SIZEALL32A));
}
else
{
SetCursor32(LoadCursor32A(0, IDC_NO32A));
}
}
}
/***
* OLEDD_TrackStateChange()
*
* This method is invoked while a drag and drop operation is in effect.
* It is used to notify the drop target/drop source callbacks when
* the state of the keyboard or mouse button change.
*
* params:
* trackerInfo - Pointer to the structure identifying the
* drag & drop operation that is currently
* active.
* mousePos - Current position of the mouse in screen
* coordinates.
* keyState - Contains the state of the shift keys and the
* mouse buttons (MK_LBUTTON and the like)
*/
static void OLEDD_TrackStateChange(
TrackerWindowInfo* trackerInfo,
POINT32 mousePos,
DWORD keyState)
{
/*
* Ask the drop source what to do with the operation.
*/
trackerInfo->returnValue = IDropSource_QueryContinueDrag(
trackerInfo->dropSource,
trackerInfo->escPressed,
keyState);
/*
* All the return valued will stop the operation except the S_OK
* return value.
*/
if (trackerInfo->returnValue!=S_OK)
{
/*
* Make sure the message loop in DoDragDrop stops
*/
trackerInfo->trackingDone = TRUE;
/*
* Release the mouse in case the drop target decides to show a popup
* or a menu or something.
*/
ReleaseCapture();
/*
* If we end-up over a target, drop the object in the target or
* inform the target that the operation was cancelled.
*/
if (trackerInfo->curDragTarget!=0)
{
switch (trackerInfo->returnValue)
{
/*
* If the source wants us to complete the operation, we tell
* the drop target that we just dropped the object in it.
*/
case DRAGDROP_S_DROP:
{
POINTL mousePosParam;
/*
* The documentation tells me that the coordinate should be
* in the target window's coordinate space. However, the tests
* I made tell me the coordinates should be in screen coordinates.
*/
mousePosParam.x = mousePos.x;
mousePosParam.y = mousePos.y;
IDropTarget_Drop(trackerInfo->curDragTarget,
trackerInfo->dataObject,
keyState,
mousePosParam,
trackerInfo->pdwEffect);
break;
}
/*
* If the source told us that we should cancel, fool the drop
* target by telling it that the mouse left it's window.
*/
case DRAGDROP_S_CANCEL:
IDropTarget_DragLeave(trackerInfo->curDragTarget);
break;
}
}
}
}
/***
* OLEDD_GetButtonState()
*
* This method will use the current state of the keyboard to build
* a button state mask equivalent to the one passed in the
* WM_MOUSEMOVE wParam.
*/
static DWORD OLEDD_GetButtonState()
{
BYTE keyboardState[256];
DWORD keyMask = 0;
GetKeyboardState(keyboardState);
if ( (keyboardState[VK_SHIFT] & 0x80) !=0)
keyMask |= MK_SHIFT;
if ( (keyboardState[VK_CONTROL] & 0x80) !=0)
keyMask |= MK_CONTROL;
if ( (keyboardState[VK_LBUTTON] & 0x80) !=0)
keyMask |= MK_LBUTTON;
if ( (keyboardState[VK_RBUTTON] & 0x80) !=0)
keyMask |= MK_RBUTTON;
if ( (keyboardState[VK_MBUTTON] & 0x80) !=0)
keyMask |= MK_MBUTTON;
return keyMask;
}

View File

@ -105,7 +105,7 @@ type win32
102 stub OleDuplicateData
103 stub OleFlushClipboard
104 stub OleGetAutoConvert
105 stub OleGetClipboard
105 stdcall OleGetClipboard(ptr) OleGetClipboard32
106 stub OleGetIconOfClass
107 stub OleGetIconOfFile
108 stdcall OleInitialize(ptr) OleInitialize
@ -118,10 +118,10 @@ type win32
115 stub OleMetafilePictFromIconAndLabel
116 stub OleNoteObjectVisible
117 stub OleQueryCreateFromData
118 stub OleQueryLinkFromData
118 stdcall OleQueryLinkFromData(ptr) OleQueryLinkFromData32
119 stub OleRegEnumFormatEtc
120 stub OleRegEnumVerbs
121 stub OleRegGetMiscStatus
121 stdcall OleRegGetMiscStatus(ptr long ptr) OleRegGetMiscStatus32
122 stdcall OleRegGetUserType(long long ptr) OleRegGetUserType32
123 stub OleRun
124 stub OleSave