mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[SHELL32] CFSDropTarget: Initial implementation of right click drag menu
This commit is contained in:
parent
8f8ab050db
commit
6d91269eda
2 changed files with 123 additions and 4 deletions
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue