wine/dlls/shell32 shlview.c

Alexandre Julliard julliard at wine.codeweavers.com
Fri Dec 2 07:14:58 CST 2005


ChangeSet ID:	21623
CVSROOT:	/opt/cvs-commit
Module name:	wine
Changes by:	julliard at winehq.org	2005/12/02 07:14:58

Modified files:
	dlls/shell32   : shlview.c 

Log message:
	Michael Jung <mjung at iss.tu-darmstadt.de>
	Implemented scrolling during drag&drop for the shellview class.

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

Old revision  New revision  Changes     Path
 1.122         1.123         +67 -2      wine/dlls/shell32/shlview.c

Index: wine/dlls/shell32/shlview.c
diff -u -p wine/dlls/shell32/shlview.c:1.122 wine/dlls/shell32/shlview.c:1.123
--- wine/dlls/shell32/shlview.c:1.122	2 Dec 2005 13:14:58 -0000
+++ wine/dlls/shell32/shlview.c	2 Dec 2005 13:14:58 -0000
@@ -103,6 +103,7 @@ typedef struct
         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 */
+        UINT            iActiveTimersMask; /* Bookkeeping of activated timers for drag scrolling */
 } IShellViewImpl;
 
 static const IShellViewVtbl svvt;
@@ -196,6 +197,7 @@ IShellView * IShellView_Constructor( ISh
         sv->pCurDropTarget = NULL;
         sv->pCurDataObject = NULL;
         sv->iDragOverItem = 0;
+        sv->iActiveTimersMask = 0;
 
 	TRACE("(%p)->(%p)\n",sv, pFolder);
 	return (IShellView *) sv;
@@ -2177,11 +2179,56 @@ static ULONG WINAPI ISVDropTarget_Releas
 }
 
 /******************************************************************************
+ * scroll_timer_proc [Internal]
+ *
+ * Timer callback function for drag&drop scrolling
+ */
+
+#define IDT_UP    0x1u
+#define IDT_DOWN  0x2u
+#define IDT_LEFT  0x4u
+#define IDT_RIGHT 0x8u
+
+VOID CALLBACK scroll_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idTimer, DWORD dwTimer) {
+    switch (idTimer) {
+        case IDT_UP:
+            SendMessageW(hwnd, WM_VSCROLL, SB_LINEUP, 0);
+            break;
+        case IDT_DOWN:
+            SendMessageW(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
+            break;
+        case IDT_LEFT:
+            SendMessageW(hwnd, WM_HSCROLL, SB_LINEUP, 0);
+            break;
+        case IDT_RIGHT:
+            SendMessageW(hwnd, WM_HSCROLL, SB_LINEDOWN, 0);
+            break;
+    }
+}
+
+/******************************************************************************
+ * start_stop_timer [Internal]
+ */
+static inline void start_stop_timer(IShellViewImpl *This, UINT_PTR idTimer, BOOL fStart) {
+    if (fStart && !(This->iActiveTimersMask & idTimer)) {
+        SetTimer(This->hWndList, idTimer, 200, scroll_timer_proc);
+        This->iActiveTimersMask |= idTimer;
+    }
+    if (!fStart && This->iActiveTimersMask & idTimer) {
+        KillTimer(This->hWndList, idTimer);
+        This->iActiveTimersMask &= ~idTimer;
+    }
+}
+
+/******************************************************************************
  * drag_notify_subitem [Internal]
  *
  * Figure out the shellfolder object, which is currently under the mouse cursor
  * and notify it via the IDropTarget interface.
  */
+
+#define SCROLLAREAWIDTH 20
+
 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
     DWORD *pdwEffect)
 {
@@ -2189,15 +2236,23 @@ static HRESULT drag_notify_subitem(IShel
     LVITEMA lvItem;
     LONG lResult;
     HRESULT hr;
+    RECT clientRect;
 
     /* 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);
+    ScreenToClient(This->hWndList, &htinfo.pt);
     lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
 
+    /* Start or stop the drag scrolling timers */
+    GetClientRect(This->hWndList, &clientRect);
+    start_stop_timer(This, IDT_LEFT,  htinfo.pt.x < SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_RIGHT, htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_UP,    htinfo.pt.y < SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_DOWN,  htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH);
+
     /* 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);
@@ -2265,7 +2320,12 @@ static HRESULT WINAPI ISVDropTarget_Drag
     This->pCurDataObject = NULL;
     This->pCurDropTarget = NULL;
     This->iDragOverItem = 0;
-        
+     
+    start_stop_timer(This, IDT_LEFT,  FALSE);
+    start_stop_timer(This, IDT_RIGHT, FALSE);
+    start_stop_timer(This, IDT_UP,    FALSE);
+    start_stop_timer(This, IDT_DOWN,  FALSE);
+   
     return S_OK;
 }
 
@@ -2282,6 +2342,11 @@ static HRESULT WINAPI ISVDropTarget_Drop
     This->pCurDropTarget = NULL;
     This->iDragOverItem = 0;
 
+    start_stop_timer(This, IDT_LEFT,  FALSE);
+    start_stop_timer(This, IDT_RIGHT, FALSE);
+    start_stop_timer(This, IDT_UP,    FALSE);
+    start_stop_timer(This, IDT_DOWN,  FALSE);
+   
     return S_OK;
 }
 



More information about the wine-cvs mailing list