https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6d91269edaf26cbea01957...
commit 6d91269edaf26cbea019577b9b14faf7d04a8d33 Author: Giannis Adamopoulos gadamopoulos@reactos.org AuthorDate: Fri Feb 16 20:33:44 2018 +0200 Commit: Giannis Adamopoulos gadamopoulos@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()
};