https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6d91269edaf26cbea0195…
commit 6d91269edaf26cbea019577b9b14faf7d04a8d33
Author: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
AuthorDate: Fri Feb 16 20:33:44 2018 +0200
Commit: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
CommitDate: Sat Feb 17 20:30:37 2018 +0200
[SHELL32] CFSDropTarget: Initial implementation of right click drag menu
---
dll/win32/shell32/droptargets/CFSDropTarget.cpp | 114 +++++++++++++++++++++++-
dll/win32/shell32/droptargets/CFSDropTarget.h | 13 ++-
2 files changed, 123 insertions(+), 4 deletions(-)
diff --git a/dll/win32/shell32/droptargets/CFSDropTarget.cpp
b/dll/win32/shell32/droptargets/CFSDropTarget.cpp
index 468f6c1703..3337b455a0 100644
--- a/dll/win32/shell32/droptargets/CFSDropTarget.cpp
+++ b/dll/win32/shell32/droptargets/CFSDropTarget.cpp
@@ -83,7 +83,7 @@ HRESULT WINAPI CFSDropTarget::CopyItems(IShellFolder * pSFFrom, UINT
cidl,
SHFILEOPSTRUCTW op = {0};
op.pFrom = pszSrcList;
op.pTo = wszTargetPath;
- op.hwnd = GetActiveWindow();
+ op.hwnd = m_hwndSite;
op.wFunc = bCopy ? FO_COPY : FO_MOVE;
op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
@@ -100,7 +100,9 @@ HRESULT WINAPI CFSDropTarget::CopyItems(IShellFolder * pSFFrom, UINT
cidl,
CFSDropTarget::CFSDropTarget():
cfShellIDList(0),
fAcceptFmt(FALSE),
- sPathTarget(NULL)
+ sPathTarget(NULL),
+ m_hwndSite(NULL),
+ m_grfKeyState(0)
{
}
@@ -180,6 +182,70 @@ BOOL CFSDropTarget::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
return FALSE;
}
+HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD
*pdwEffect)
+{
+ HMENU hmenu = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(IDM_DRAGFILE));
+ if (!hmenu)
+ return E_OUTOFMEMORY;
+
+ /* FIXME: We need to support shell extensions here */
+
+ UINT uCommand = TrackPopupMenu(GetSubMenu(hmenu, 0),
+ TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON |
TPM_RIGHTBUTTON,
+ pt.x, pt.y, 0, m_hwndSite, NULL);
+ if (uCommand == 0)
+ return S_FALSE;
+ else if (uCommand == IDM_COPYHERE)
+ *pdwEffect = DROPEFFECT_COPY;
+ else if (uCommand == IDM_MOVEHERE)
+ *pdwEffect = DROPEFFECT_MOVE;
+ else if (uCommand == IDM_LINKHERE)
+ *pdwEffect = DROPEFFECT_LINK;
+
+ return S_OK;
+}
+
+HRESULT CFSDropTarget::_RepositionItems(IShellFolderView *psfv, IDataObject *pdtobj,
POINTL pt)
+{
+ CComPtr<IFolderView> pfv;
+ POINT ptDrag;
+ HRESULT hr = psfv->QueryInterface(IID_PPV_ARG(IFolderView, &pfv));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ hr = psfv->GetDragPoint(&ptDrag);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ PIDLIST_ABSOLUTE pidlFolder;
+ PUITEMID_CHILD *apidl;
+ UINT cidl;
+ hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ CComHeapPtr<POINT> apt;
+ if (!apt.Allocate(cidl))
+ {
+ SHFree(pidlFolder);
+ _ILFreeaPidl(apidl, cidl);
+ return E_OUTOFMEMORY;
+ }
+
+ for (UINT i = 0; i<cidl; i++)
+ {
+ pfv->GetItemPosition(apidl[i], &apt[i]);
+ apt[i].x += pt.x - ptDrag.x;
+ apt[i].y += pt.y - ptDrag.y;
+ }
+
+ pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT);
+
+ SHFree(pidlFolder);
+ _ILFreeaPidl(apidl, cidl);
+ return S_OK;
+}
+
HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
{
@@ -196,6 +262,8 @@ HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
fAcceptFmt = TRUE;
+ m_grfKeyState = dwKeyState;
+
QueryDrop(dwKeyState, pdwEffect);
return S_OK;
}
@@ -208,6 +276,8 @@ HRESULT WINAPI CFSDropTarget::DragOver(DWORD dwKeyState, POINTL pt,
if (!pdwEffect)
return E_INVALIDARG;
+ m_grfKeyState = dwKeyState;
+
QueryDrop(dwKeyState, pdwEffect);
return S_OK;
@@ -230,8 +300,28 @@ HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
if (!pdwEffect)
return E_INVALIDARG;
+ IUnknown_GetWindow(m_site, &m_hwndSite);
+
QueryDrop(dwKeyState, pdwEffect);
+ if (m_grfKeyState & MK_RBUTTON)
+ {
+ HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect);
+ if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE)
+ return hr;
+ }
+
+ if (*pdwEffect == DROPEFFECT_MOVE && m_site)
+ {
+ CComPtr<IShellFolderView> psfv;
+ HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView,
IID_PPV_ARG(IShellFolderView, &psfv));
+ if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK)
+ {
+ _RepositionItems(psfv, pDataObject, pt);
+ return S_OK;
+ }
+ }
+
BOOL fIsOpAsync = FALSE;
CComPtr<IAsyncOperation> pAsyncOperation;
@@ -257,6 +347,24 @@ HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
}
+HRESULT
+WINAPI
+CFSDropTarget::SetSite(IUnknown *pUnkSite)
+{
+ m_site = pUnkSite;
+ return S_OK;
+}
+
+HRESULT
+WINAPI
+CFSDropTarget::GetSite(REFIID riid, void **ppvSite)
+{
+ if (!m_site)
+ return E_FAIL;
+
+ return m_site->QueryInterface(riid, ppvSite);
+}
+
HRESULT WINAPI CFSDropTarget::_DoDrop(IDataObject *pDataObject,
DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
{
@@ -474,7 +582,7 @@ HRESULT WINAPI CFSDropTarget::_DoDrop(IDataObject *pDataObject,
ZeroMemory(&op, sizeof(op));
op.pFrom = pszSrcList;
op.pTo = wszTargetPath;
- op.hwnd = GetActiveWindow();
+ op.hwnd = m_hwndSite;
op.wFunc = bCopy ? FO_COPY : FO_MOVE;
op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
hr = SHFileOperationW(&op);
diff --git a/dll/win32/shell32/droptargets/CFSDropTarget.h
b/dll/win32/shell32/droptargets/CFSDropTarget.h
index e6c063d02c..091e60ee33 100644
--- a/dll/win32/shell32/droptargets/CFSDropTarget.h
+++ b/dll/win32/shell32/droptargets/CFSDropTarget.h
@@ -25,18 +25,24 @@
class CFSDropTarget :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
- public IDropTarget
+ public IDropTarget,
+ public IObjectWithSite
{
private:
UINT cfShellIDList; /* clipboardformat for IDropTarget */
BOOL fAcceptFmt; /* flag for pending Drop */
LPWSTR sPathTarget;
+ HWND m_hwndSite;
+ DWORD m_grfKeyState;
+ CComPtr<IUnknown> m_site;
BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
virtual HRESULT WINAPI _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL
pt, DWORD *pdwEffect);
virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST
*apidl, BOOL bCopy);
BOOL GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget,
BOOL bShortcut);
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter);
+ HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD
*pdwEffect);
+ HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL
pt);
public:
CFSDropTarget();
@@ -49,12 +55,17 @@ class CFSDropTarget :
virtual HRESULT WINAPI DragLeave();
virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL
pt, DWORD *pdwEffect);
+ // IObjectWithSite
+ virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
+ virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
+
DECLARE_NOT_AGGREGATABLE(CFSDropTarget)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CFSDropTarget)
COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
+ COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
END_COM_MAP()
};