Sync to Wine-0_9_3:
Michael Jung <mjung(a)iss.tu-darmstadt.de>
- Use the ANSI codepage in IShellFolder::GetDisplayNameOf.
- Implemented scrolling during drag&drop for the shellview class.
- Use GetUIObjectOf instead of BindToObject to get a IDropTarget object.
- 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.
- Initialize OLE instead of just COM, in order to enable Drag & Drop.
- Modified KeyStateToDropEffect macro to match native shellview's
behaviour.
- Also scan HKEY_CURRENT_USER for shell namespace extensions in Desktop
folder.
Fixed a handle leak in case of failing AddToEnumList call.
- Also scan HKEY_CURRENT_USER for shell namespace extensions in
MyComputer.
- Enhanced UnixFolder's IDropTarget implementation.
Use STATIC_CAST macro more consistently.
- Initial stubbed implementation of UnixFolder's IDropTarget interface.
Francois Gouget <fgouget(a)free.fr>
- Assorted spelling fixes.
Ge van Geldorp <gvg(a)reactos.org>
- Load shortcut icon by resource id instead of by icon index.
- Other code in shlexec.c (e.g. the extension handling code in
ShellExecute_GetClassKey) expects sei->lpFile to not be enclosed in
quotes.
Martin Fuchs <martin-fuchs(a)gmx.net>
- Correctly call HCR_GetFolderAttributes() in
SHELL32_GetItemAttributes().
Directly return the correct "My Computer" attributes in
ISF_Desktop_fnGetAttributesOf().
Remove "todo_wine" from the "My Computer" attributes test case.
Add test case for retrieving the file system path from the
CSIDL_PROGRAM_FILES PIDL using SHGetPathFromIDListW().
- Fix context menu handling for more than one entry in order to repair
.lnk-file execution: Don't break at the first non-matching entry.
Markus Gömmel <m.goemmel(a)compulab.de>
- Added CSIDL_MYVIDEO|MYPICTURES|MYMUSIC to _SHRegisterUserShellFolders.
Modified: trunk/reactos/lib/shell32/iconcache.c
Modified: trunk/reactos/lib/shell32/shell32_main.h
Modified: trunk/reactos/lib/shell32/shellpath.c
Modified: trunk/reactos/lib/shell32/shfldr_desktop.c
Modified: trunk/reactos/lib/shell32/shlexec.c
Modified: trunk/reactos/lib/shell32/shlview.c
_____
Modified: trunk/reactos/lib/shell32/iconcache.c
--- trunk/reactos/lib/shell32/iconcache.c 2005-12-14 19:02:42 UTC
(rev 20167)
+++ trunk/reactos/lib/shell32/iconcache.c 2005-12-14 19:09:44 UTC
(rev 20168)
@@ -129,7 +129,10 @@
/* 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)
{
_____
Modified: trunk/reactos/lib/shell32/shell32_main.h
--- trunk/reactos/lib/shell32/shell32_main.h 2005-12-14 19:02:42 UTC
(rev 20167)
+++ trunk/reactos/lib/shell32/shell32_main.h 2005-12-14 19:09:44 UTC
(rev 20168)
@@ -121,9 +121,9 @@
};
#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);
_____
Modified: trunk/reactos/lib/shell32/shellpath.c
--- trunk/reactos/lib/shell32/shellpath.c 2005-12-14 19:02:42 UTC
(rev 20167)
+++ trunk/reactos/lib/shell32/shellpath.c 2005-12-14 19:09:44 UTC
(rev 20168)
@@ -1808,12 +1808,15 @@
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;
_____
Modified: trunk/reactos/lib/shell32/shfldr_desktop.c
--- trunk/reactos/lib/shell32/shfldr_desktop.c 2005-12-14 19:02:42 UTC
(rev 20167)
+++ trunk/reactos/lib/shell32/shfldr_desktop.c 2005-12-14 19:09:44 UTC
(rev 20168)
@@ -428,6 +428,9 @@
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 @@
pdump (*apidl);
if (_ILIsDesktop(*apidl)) {
*rgfInOut &= dwDesktopAttributes;
+ } else if (_ILIsMyComputer(*apidl)) {
+ *rgfInOut &= dwMyComputerAttributes;
} else {
SHELL32_GetItemAttributes (_IShellFolder_ (This),
*apidl, rgfInOut);
}
_____
Modified: trunk/reactos/lib/shell32/shlexec.c
--- trunk/reactos/lib/shell32/shlexec.c 2005-12-14 19:02:42 UTC (rev
20167)
+++ trunk/reactos/lib/shell32/shlexec.c 2005-12-14 19:09:44 UTC (rev
20168)
@@ -1156,15 +1156,15 @@
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 );
}
_____
Modified: trunk/reactos/lib/shell32/shlview.c
--- trunk/reactos/lib/shell32/shlview.c 2005-12-14 19:02:42 UTC (rev
20167)
+++ trunk/reactos/lib/shell32/shlview.c 2005-12-14 19:09:44 UTC (rev
20168)
@@ -100,6 +100,10 @@
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 @@
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 @@
}
}
- 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 @@
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
+ */
+
+#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)
{
+ LVHITTESTINFO htinfo;
+ LVITEMA lvItem;
+ LONG lResult;
+ HRESULT hr;
+ RECT clientRect;
- IShellViewImpl *This = impl_from_IDropTarget(iface);
+ /* 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);
- FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
+ /* 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);
- return E_NOTIMPL;
+ /* 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_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;
+
+ 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 =