wine/dlls/shell32 shlview.c

Alexandre Julliard julliard at wine.codeweavers.com
Mon Nov 28 05:03:43 CST 2005


ChangeSet ID:	21472
CVSROOT:	/opt/cvs-commit
Module name:	wine
Changes by:	julliard at winehq.org	2005/11/28 05:03:43

Modified files:
	dlls/shell32   : shlview.c 

Log message:
	Michael Jung <mjung at iss.tu-darmstadt.de>
	Register the shell view itself as the drop target, not it's parent folder.
	Forward drag&drop method calls to the folder currently under the cursor.

Patch: http://cvs.winehq.org/patch.py?id=21472

Old revision  New revision  Changes     Path
 1.120         1.121         +96 -32     wine/dlls/shell32/shlview.c

Index: wine/dlls/shell32/shlview.c
diff -u -p wine/dlls/shell32/shlview.c:1.120 wine/dlls/shell32/shlview.c:1.121
--- wine/dlls/shell32/shlview.c:1.120	28 Nov 2005 11: 3:43 -0000
+++ wine/dlls/shell32/shlview.c	28 Nov 2005 11: 3:43 -0000
@@ -100,6 +100,9 @@ typedef struct
 	DWORD		dwAspects;
 	DWORD		dwAdvf;
 	IAdviseSink    *pAdvSink;
+        IDropTarget*    pCurDropTarget; /* The sub-item, which is currently dragged over */
+        IDataObject*    pCurDataObject; /* The dragged data-object */
+        LONG            iDragOverItem;  /* Dragged over item's index, iff pCurDropTarget != NULL */
 } IShellViewImpl;
 
 static const IShellViewVtbl svvt;
@@ -190,6 +193,10 @@ IShellView * IShellView_Constructor( ISh
 	if(pFolder) IShellFolder_AddRef(pFolder);
 	IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
 
+        sv->pCurDropTarget = NULL;
+        sv->pCurDataObject = NULL;
+        sv->iDragOverItem = 0;
+
 	TRACE("(%p)->(%p)\n",sv, pFolder);
 	return (IShellView *) sv;
 }
@@ -671,7 +678,7 @@ static LRESULT ShellView_OnCreate(IShell
 	  }
 	}
 
-	if (SUCCEEDED(IShellFolder_CreateViewObject(This->pSFParent, This->hWnd, &IID_IDropTarget, (LPVOID*)&pdt)))
+        if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
 	{
 	    RegisterDragDrop(This->hWnd, pdt);
 	    IDropTarget_Release(pdt);
@@ -2169,56 +2176,113 @@ static ULONG WINAPI ISVDropTarget_Releas
 	return IShellFolder_Release((IShellFolder*)This);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragEnter(
-	IDropTarget 	*iface,
-	IDataObject	*pDataObject,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+/******************************************************************************
+ * drag_notify_subitem [Internal]
+ *
+ * Figure out the shellfolder object, which is currently under the mouse cursor
+ * and notify it via the IDropTarget interface.
+ */
+static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
+    DWORD *pdwEffect)
 {
+    LVHITTESTINFO htinfo;
+    LVITEMA lvItem;
+    LONG lResult;
+    HRESULT hr;
+
+    /* Map from global to client coordinates and query the index of the listview-item, which is 
+     * currently under the mouse cursor. */
+    htinfo.pt.x = pt.x;
+    htinfo.pt.y = pt.y;
+    htinfo.flags = LVHT_ONITEM;
+    MapWindowPoints(NULL, This->hWndList, &htinfo.pt, 1);
+    lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
+
+    /* If we are still over the previous sub-item, notify it via DragOver and return. */
+    if (This->pCurDropTarget && lResult == This->iDragOverItem)
+    return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
+  
+    /* We've left the previous sub-item, notify it via DragLeave and Release it. */
+    if (This->pCurDropTarget) {
+        IDropTarget_DragLeave(This->pCurDropTarget);
+        IDropTarget_Release(This->pCurDropTarget);
+        This->pCurDropTarget = NULL;
+    }
 
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    This->iDragOverItem = lResult;
+    if (lResult == -1) {
+        /* We are not above one of the listview's subitems. Bind to the parent folder's
+         * DropTarget interface. */
+        hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget, 
+                                         (LPVOID*)&This->pCurDropTarget);
+    } else {
+        /* Query the relative PIDL of the shellfolder object represented by the currently
+         * dragged over listview-item ... */
+        ZeroMemory(&lvItem, sizeof(lvItem));
+        lvItem.mask = LVIF_PARAM;
+        lvItem.iItem = lResult;
+        ListView_GetItemA(This->hWndList, &lvItem);
+
+        /* ... and bind pCurDropTarget to this folder's IDropTarget interface */
+        hr = IShellFolder_BindToObject(This->pSFParent, (LPITEMIDLIST)lvItem.lParam, NULL, 
+                                       &IID_IDropTarget, (LPVOID*)&This->pCurDropTarget);
+    }
 
-	FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
+    /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
+    if (FAILED(hr)) 
+        return hr;
 
-	return E_NOTIMPL;
+    /* Notify the item just entered via DragEnter. */
+    return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragOver(
-	IDropTarget	*iface,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
+    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	FIXME("Stub: This=%p\n",This);
+    /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
+    This->pCurDataObject = pDataObject;
+    IDataObject_AddRef(pDataObject);
 
-	return E_NOTIMPL;
+    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragLeave(
-	IDropTarget	*iface)
+static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
+    DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
+    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
+}
 
-	FIXME("Stub: This=%p\n",This);
+static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	return E_NOTIMPL;
+    IDropTarget_DragLeave(This->pCurDropTarget);
+
+    IDropTarget_Release(This->pCurDropTarget);
+    IDataObject_Release(This->pCurDataObject);
+    This->pCurDataObject = NULL;
+    This->pCurDropTarget = NULL;
+    This->iDragOverItem = 0;
+        
+    return S_OK;
 }
 
-static HRESULT WINAPI ISVDropTarget_Drop(
-	IDropTarget	*iface,
-	IDataObject*	pDataObject,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject, 
+    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	FIXME("Stub: This=%p\n",This);
+    IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
 
-	return E_NOTIMPL;
+    IDropTarget_Release(This->pCurDropTarget);
+    IDataObject_Release(This->pCurDataObject);
+    This->pCurDataObject = NULL;
+    This->pCurDropTarget = NULL;
+    This->iDragOverItem = 0;
+
+    return S_OK;
 }
 
 static const IDropTargetVtbl dtvt =



More information about the wine-cvs mailing list