mirror of
https://github.com/reactos/reactos.git
synced 2025-05-16 15:50:24 +00:00
[SHELL32]
- Add DoDeleteAsync method that takes the data object and the fMask parameter from IContextMenu in order to distinguish if we need a permanent delete. - CDefView: Properly add CMIC_MASK_SHIFT_DOWN and CMIC_MASK_CONTROL_DOWN flags when calling Invoke. - CDefaultContextMenu: use DoDeleteAsync and pass fmask so as to make Shift+Delete shortcut to permanently delete files. Note: GetKeyState sometimes returns wrong results but this doesn't concern the shell. CORE-4365 svn path=/trunk/; revision=69647
This commit is contained in:
parent
359fa267cc
commit
3339ceb715
4 changed files with 66 additions and 58 deletions
|
@ -151,6 +151,7 @@ class CDefView :
|
|||
void OnDeactivate();
|
||||
void DoActivate(UINT uState);
|
||||
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||
HRESULT InvokeContextMenuCommand(UINT uCommand);
|
||||
LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
|
||||
|
||||
// *** IOleWindow methods ***
|
||||
|
@ -1250,13 +1251,30 @@ UINT CDefView::GetSelections()
|
|||
return m_cidl;
|
||||
}
|
||||
|
||||
HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
|
||||
{
|
||||
CMINVOKECOMMANDINFO cmi;
|
||||
|
||||
ZeroMemory(&cmi, sizeof(cmi));
|
||||
cmi.cbSize = sizeof(cmi);
|
||||
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
|
||||
cmi.hwnd = m_hWnd;
|
||||
|
||||
if (GetKeyState(VK_SHIFT) & 0x8000)
|
||||
cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
|
||||
|
||||
if (GetKeyState(VK_CONTROL) & 0x8000)
|
||||
cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
|
||||
|
||||
return m_pCM->InvokeCommand(&cmi);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* ShellView_OpenSelectedItems()
|
||||
*/
|
||||
HRESULT CDefView::OpenSelectedItems()
|
||||
{
|
||||
HMENU hMenu;
|
||||
CMINVOKECOMMANDINFO cmi;
|
||||
UINT uCommand;
|
||||
HRESULT hResult;
|
||||
|
||||
|
@ -1287,12 +1305,7 @@ HRESULT CDefView::OpenSelectedItems()
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
ZeroMemory(&cmi, sizeof(cmi));
|
||||
cmi.cbSize = sizeof(cmi);
|
||||
cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
|
||||
cmi.hwnd = m_hWnd;
|
||||
|
||||
hResult = m_pCM->InvokeCommand(&cmi);
|
||||
InvokeContextMenuCommand(uCommand);
|
||||
|
||||
cleanup:
|
||||
|
||||
|
@ -1314,7 +1327,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
|
|||
WORD y;
|
||||
UINT uCommand;
|
||||
HMENU hMenu;
|
||||
CMINVOKECOMMANDINFO cmi;
|
||||
HRESULT hResult;
|
||||
|
||||
// for some reason I haven't figured out, we sometimes recurse into this method
|
||||
|
@ -1340,9 +1352,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
|
|||
if (FAILED( hResult))
|
||||
goto cleanup;
|
||||
|
||||
if (m_FolderSettings.fFlags & FWF_DESKTOP)
|
||||
SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
|
||||
|
||||
uCommand = TrackPopupMenu(hMenu,
|
||||
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
|
||||
x, y, 0, m_hWnd, NULL);
|
||||
|
@ -1352,14 +1361,9 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
|
|||
if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
|
||||
goto cleanup;
|
||||
|
||||
ZeroMemory(&cmi, sizeof(cmi));
|
||||
cmi.cbSize = sizeof(cmi);
|
||||
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
|
||||
cmi.hwnd = m_hWnd;
|
||||
m_pCM->InvokeCommand(&cmi);
|
||||
InvokeContextMenuCommand(uCommand);
|
||||
|
||||
cleanup:
|
||||
|
||||
if (m_pCM)
|
||||
m_pCM.Release();
|
||||
|
||||
|
@ -1372,7 +1376,6 @@ cleanup:
|
|||
LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
|
||||
{
|
||||
HRESULT hResult;
|
||||
CMINVOKECOMMANDINFO cmi;
|
||||
HMENU hMenu;
|
||||
|
||||
hMenu = CreatePopupMenu();
|
||||
|
@ -1387,14 +1390,9 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
|
|||
if (FAILED( hResult))
|
||||
goto cleanup;
|
||||
|
||||
ZeroMemory(&cmi, sizeof(cmi));
|
||||
cmi.cbSize = sizeof(cmi);
|
||||
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
|
||||
cmi.hwnd = m_hWnd;
|
||||
m_pCM->InvokeCommand(&cmi);
|
||||
InvokeContextMenuCommand(uCommand);
|
||||
|
||||
cleanup:
|
||||
|
||||
if (m_pCM)
|
||||
m_pCM.Release();
|
||||
|
||||
|
|
|
@ -1165,19 +1165,9 @@ CDefaultContextMenu::DoCreateLink(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) {
|
||||
TRACE("(%p) Deleting\n", this);
|
||||
|
||||
CComPtr<IDataObject> pDataObject;
|
||||
|
||||
if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObject))))
|
||||
{
|
||||
IStream *s;
|
||||
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
|
||||
SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
|
||||
}
|
||||
else
|
||||
return E_FAIL;
|
||||
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
|
||||
{
|
||||
DoDeleteAsync(m_pDataObj, lpcmi->fMask);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1030,10 +1030,14 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
|
|||
InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
|
||||
|
||||
/* Handle cfShellIDList Drop objects here, otherwise send the approriate message to other software */
|
||||
if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) {
|
||||
IStream *s;
|
||||
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
|
||||
SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
|
||||
if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
|
||||
{
|
||||
DWORD fMask = 0;
|
||||
|
||||
if ((dwKeyState & MK_SHIFT) == MK_SHIFT)
|
||||
fMask |= CMIC_MASK_SHIFT_DOWN;
|
||||
|
||||
DoDeleteAsync(pDataObject, fMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1045,20 +1049,7 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
CComPtr<IDataObject> pDataObject;
|
||||
HRESULT hr = CoGetInterfaceAndReleaseStream (static_cast<IStream*>(lpParameter), IID_PPV_ARG(IDataObject, &pDataObject));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DoDeleteDataObject(pDataObject);
|
||||
}
|
||||
CoUninitialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
|
||||
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda, DWORD fMask)
|
||||
{
|
||||
TRACE("performing delete");
|
||||
HRESULT hr;
|
||||
|
@ -1160,7 +1151,8 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
|
|||
ZeroMemory(&FileOp, sizeof(FileOp));
|
||||
FileOp.wFunc = FO_DELETE;
|
||||
FileOp.pFrom = pwszPaths;
|
||||
FileOp.fFlags = FOF_ALLOWUNDO;
|
||||
if ((fMask & CMIC_MASK_SHIFT_DOWN) == 0)
|
||||
FileOp.fFlags = FOF_ALLOWUNDO;
|
||||
|
||||
if (SHFileOperationW(&FileOp) != 0)
|
||||
{
|
||||
|
@ -1176,6 +1168,35 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
|
|||
return hr;
|
||||
}
|
||||
|
||||
struct DeleteThreadData {
|
||||
IStream *s;
|
||||
DWORD fMask;
|
||||
};
|
||||
|
||||
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
DeleteThreadData *data = static_cast<DeleteThreadData*>(lpParameter);
|
||||
CoInitialize(NULL);
|
||||
IDataObject *pDataObject;
|
||||
HRESULT hr = CoGetInterfaceAndReleaseStream (data->s, IID_PPV_ARG(IDataObject, &pDataObject));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DoDeleteDataObject(pDataObject, data->fMask);
|
||||
}
|
||||
pDataObject->Release();
|
||||
CoUninitialize();
|
||||
HeapFree(GetProcessHeap(), 0, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DoDeleteAsync(IDataObject *pda, DWORD fMask)
|
||||
{
|
||||
DeleteThreadData *data = static_cast<DeleteThreadData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(DeleteThreadData)));
|
||||
data->fMask = fMask;
|
||||
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pda, &data->s);
|
||||
SHCreateThread(DoDeleteThreadProc, data, NULL, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHEmptyRecycleBinA (SHELL32.@)
|
||||
*/
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#ifndef _SHFLDR_RECYCLEBIN_H_
|
||||
#define _SHFLDR_RECYCLEBIN_H_
|
||||
|
||||
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter);
|
||||
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda);
|
||||
void DoDeleteAsync(IDataObject *pda, DWORD fMask);
|
||||
|
||||
BOOL TRASH_CanTrashFile(LPCWSTR wszPath);
|
||||
BOOL TRASH_TrashFile(LPCWSTR wszPath);
|
||||
|
|
Loading…
Reference in a new issue