ChangeSet ID: 21623 CVSROOT: /opt/cvs-commit Module name: wine Changes by: julliard@winehq.org 2005/12/02 07:14:58
Modified files: dlls/shell32 : shlview.c
Log message: Michael Jung mjung@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; }