From f01f1be7e9b5e697fbfe31a7dc7c241301b85f28 Mon Sep 17 00:00:00 2001 From: =?utf8?q?G=C3=A9=20van=20Geldorp?= Date: Wed, 14 Dec 2005 19:09:44 +0000 Subject: [PATCH] =?utf8?q?Sync=20to=20Wine-0=5F9=5F3:=20Michael=20Jung=20=20-=20Use=20the=20ANSI=20codepage=20i?= =?utf8?q?n=20IShellFolder::GetDisplayNameOf.=20-=20Implemented=20scrollin?= =?utf8?q?g=20during=20drag&drop=20for=20the=20shellview=20class.=20-=20Us?= =?utf8?q?e=20GetUIObjectOf=20instead=20of=20BindToObject=20to=20get=20a?= =?utf8?q?=20IDropTarget=20object.=20-=20Register=20the=20shell=20view=20i?= =?utf8?q?tself=20as=20the=20drop=20target,=20not=20it's=20parent=20folder?= =?utf8?q?.=20=20=20Forward=20drag&drop=20method=20calls=20to=20the=20fold?= =?utf8?q?er=20currently=20under=20the=20cursor.=20-=20Initialize=20OLE=20?= =?utf8?q?instead=20of=20just=20COM,=20in=20order=20to=20enable=20Drag=20&?= =?utf8?q?=20Drop.=20-=20Modified=20KeyStateToDropEffect=20macro=20to=20ma?= =?utf8?q?tch=20native=20shellview's=20=20=20behaviour.=20-=20Also=20scan?= =?utf8?q?=20HKEY=5FCURRENT=5FUSER=20for=20shell=20namespace=20extensions?= =?utf8?q?=20in=20Desktop=20=20=20folder.=20=20=20Fixed=20a=20handle=20lea?= =?utf8?q?k=20in=20case=20of=20failing=20AddToEnumList=20call.=20-=20Also?= =?utf8?q?=20scan=20HKEY=5FCURRENT=5FUSER=20for=20shell=20namespace=20exte?= =?utf8?q?nsions=20in=20=20=20MyComputer.=20-=20Enhanced=20UnixFolder's=20?= =?utf8?q?IDropTarget=20implementation.=20=20=20Use=20STATIC=5FCAST=20macr?= =?utf8?q?o=20more=20consistently.=20-=20Initial=20stubbed=20implementatio?= =?utf8?q?n=20of=20UnixFolder's=20IDropTarget=20interface.=20Francois=20Go?= =?utf8?q?uget=20=20-=20Assorted=20spelling=20fixes.=20Ge?= =?utf8?q?=20van=20Geldorp=20=20-=20Load=20shortcut=20ico?= =?utf8?q?n=20by=20resource=20id=20instead=20of=20by=20icon=20index.=20-?= =?utf8?q?=20Other=20code=20in=20shlexec.c=20(e.g.=20the=20extension=20han?= =?utf8?q?dling=20code=20in=20=20=20ShellExecute=5FGetClassKey)=20expects?= =?utf8?q?=20sei->lpFile=20to=20not=20be=20enclosed=20in=20=20=20quotes.?= =?utf8?q?=20Martin=20Fuchs=20=20-=20Correctly=20cal?= =?utf8?q?l=20HCR=5FGetFolderAttributes()=20in=20SHELL32=5FGetItemAttribut?= =?utf8?q?es().=20=20=20Directly=20return=20the=20correct=20"My=20Computer?= =?utf8?q?"=20attributes=20in=20=20=20ISF=5FDesktop=5FfnGetAttributesOf().?= =?utf8?q?=20=20=20Remove=20"todo=5Fwine"=20from=20the=20"My=20Computer"?= =?utf8?q?=20attributes=20test=20case.=20=20=20Add=20test=20case=20for=20r?= =?utf8?q?etrieving=20the=20file=20system=20path=20from=20the=20=20=20CSID?= =?utf8?q?L=5FPROGRAM=5FFILES=20PIDL=20using=20SHGetPathFromIDListW().=20-?= =?utf8?q?=20Fix=20context=20menu=20handling=20for=20more=20than=20one=20e?= =?utf8?q?ntry=20in=20order=20to=20repair=20=20=20.lnk-file=20execution:?= =?utf8?q?=20Don't=20break=20at=20the=20first=20non-matching=20entry.=20Ma?= =?utf8?q?rkus=20G=C3=B6mmel=20=20-=20Added=20CSIDL?= =?utf8?q?=5FMYVIDEO|MYPICTURES|MYMUSIC=20to=20=5FSHRegisterUserShellFolde?= =?utf8?q?rs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit svn path=/trunk/; revision=20168 --- reactos/lib/shell32/iconcache.c | 5 +- reactos/lib/shell32/shell32_main.h | 6 +- reactos/lib/shell32/shellpath.c | 3 + reactos/lib/shell32/shfldr_desktop.c | 5 + reactos/lib/shell32/shlexec.c | 16 +-- reactos/lib/shell32/shlview.c | 195 ++++++++++++++++++++++----- 6 files changed, 185 insertions(+), 45 deletions(-) diff --git a/reactos/lib/shell32/iconcache.c b/reactos/lib/shell32/iconcache.c index 3efefcfbb21..0008f34f386 100644 --- a/reactos/lib/shell32/iconcache.c +++ b/reactos/lib/shell32/iconcache.c @@ -129,7 +129,10 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large) /* search for the shortcut icon only once */ if (s_imgListIdx == -1) - s_imgListIdx = SIC_LoadOverlayIcon(-IDI_SHELL_SHORTCUT); + s_imgListIdx = SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT); + /* FIXME should use icon index 29 instead of the + resource id, but not all icons are present yet + so we can't use icon indices */ if (s_imgListIdx != -1) { diff --git a/reactos/lib/shell32/shell32_main.h b/reactos/lib/shell32/shell32_main.h index c67fa7fc7bf..3d8be2542fc 100644 --- a/reactos/lib/shell32/shell32_main.h +++ b/reactos/lib/shell32/shell32_main.h @@ -121,9 +121,9 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI }; #define KeyStateToDropEffect(kst)\ - (((kst) & MK_CONTROL) ?\ - (((kst) & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY):\ - DROPEFFECT_MOVE) + ((((kst)&(MK_CONTROL|MK_SHIFT))==(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_LINK :\ + (((kst)&(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_COPY :\ + DROPEFFECT_MOVE)) HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); diff --git a/reactos/lib/shell32/shellpath.c b/reactos/lib/shell32/shellpath.c index 27a5b13de85..fe6aef134d7 100644 --- a/reactos/lib/shell32/shellpath.c +++ b/reactos/lib/shell32/shellpath.c @@ -1808,12 +1808,15 @@ static HRESULT _SHRegisterUserShellFolders(BOOL bDefault) CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU, + CSIDL_MYMUSIC, + CSIDL_MYVIDEO, CSIDL_DESKTOPDIRECTORY, CSIDL_NETHOOD, CSIDL_TEMPLATES, CSIDL_PRINTHOOD, CSIDL_COOKIES, CSIDL_HISTORY, + CSIDL_MYPICTURES }; WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH]; LPCWSTR pUserShellFolderPath, pShellFolderPath; diff --git a/reactos/lib/shell32/shfldr_desktop.c b/reactos/lib/shell32/shfldr_desktop.c index 800a857677d..74f720050b7 100644 --- a/reactos/lib/shell32/shfldr_desktop.c +++ b/reactos/lib/shell32/shfldr_desktop.c @@ -428,6 +428,9 @@ static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface, static const DWORD dwDesktopAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER; + static const DWORD dwMyComputerAttributes = + SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | + SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n", This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); @@ -447,6 +450,8 @@ static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface, pdump (*apidl); if (_ILIsDesktop(*apidl)) { *rgfInOut &= dwDesktopAttributes; + } else if (_ILIsMyComputer(*apidl)) { + *rgfInOut &= dwMyComputerAttributes; } else { SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); } diff --git a/reactos/lib/shell32/shlexec.c b/reactos/lib/shell32/shlexec.c index 0e4d30df458..350ad7da0da 100644 --- a/reactos/lib/shell32/shlexec.c +++ b/reactos/lib/shell32/shlexec.c @@ -1156,15 +1156,15 @@ static LONG ShellExecute_FromContextMenu( LPSHELLEXECUTEINFOW sei ) r = RegEnumKeyW( hkeycm, i++, szguid, 39 ); if ( r != ERROR_SUCCESS ) break; - r = ERROR_FUNCTION_FAILED; + hr = CLSIDFromString( szguid, &guid ); - if ( FAILED( hr ) ) - break; - r = ERROR_SUCCESS; - /* stop at the first one that succeeds in running */ - hr = shellex_load_object_and_run( hkey, &guid, sei ); - if ( SUCCEEDED( hr ) ) - break; + if (SUCCEEDED(hr)) + { + /* stop at the first one that succeeds in running */ + hr = shellex_load_object_and_run( hkey, &guid, sei ); + if ( SUCCEEDED( hr ) ) + break; + } } RegCloseKey( hkeycm ); } diff --git a/reactos/lib/shell32/shlview.c b/reactos/lib/shell32/shlview.c index a024933797f..99ca8629f3b 100644 --- a/reactos/lib/shell32/shlview.c +++ b/reactos/lib/shell32/shlview.c @@ -100,6 +100,10 @@ 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 */ + UINT iActiveTimersMask; /* Bookkeeping of activated timers for drag scrolling */ } IShellViewImpl; static const IShellViewVtbl svvt; @@ -190,6 +194,11 @@ IShellView * IShellView_Constructor( IShellFolder * pFolder) if(pFolder) IShellFolder_AddRef(pFolder); IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent); + sv->pCurDropTarget = NULL; + sv->pCurDataObject = NULL; + sv->iDragOverItem = 0; + sv->iActiveTimersMask = 0; + TRACE("(%p)->(%p)\n",sv, pFolder); return (IShellView *) sv; } @@ -671,7 +680,7 @@ static LRESULT ShellView_OnCreate(IShellViewImpl * This) } } - 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 +2178,176 @@ static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface) return IShellFolder_Release((IShellFolder*)This); } -static HRESULT WINAPI ISVDropTarget_DragEnter( - IDropTarget *iface, - IDataObject *pDataObject, - DWORD grfKeyState, - POINTL pt, - DWORD *pdwEffect) -{ +/****************************************************************************** + * scroll_timer_proc [Internal] + * + * Timer callback function for drag&drop scrolling + */ - IShellViewImpl *This = impl_from_IDropTarget(iface); +#define IDT_UP 0x1u +#define IDT_DOWN 0x2u +#define IDT_LEFT 0x4u +#define IDT_RIGHT 0x8u - FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject); +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; + } +} - return E_NOTIMPL; +/****************************************************************************** + * 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; + } } -static HRESULT WINAPI ISVDropTarget_DragOver( - IDropTarget *iface, - 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. + */ + +#define SCROLLAREAWIDTH 20 + +static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt, + DWORD *pdwEffect) +{ + LVHITTESTINFO htinfo; + 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; + 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); + + /* 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; + } + + 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 the IDropTarget interface of an UIObject of this object */ + hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1, + (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget); + } + + /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */ + if (FAILED(hr)) + return hr; + + /* Notify the item just entered via DragEnter. */ + return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, 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; + + 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; } -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; + + 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; } static const IDropTargetVtbl dtvt = -- 2.17.1