mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:42:57 +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 OnDeactivate();
|
||||||
void DoActivate(UINT uState);
|
void DoActivate(UINT uState);
|
||||||
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
HRESULT InvokeContextMenuCommand(UINT uCommand);
|
||||||
LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
|
LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
|
||||||
|
|
||||||
// *** IOleWindow methods ***
|
// *** IOleWindow methods ***
|
||||||
|
@ -1250,13 +1251,30 @@ UINT CDefView::GetSelections()
|
||||||
return m_cidl;
|
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()
|
* ShellView_OpenSelectedItems()
|
||||||
*/
|
*/
|
||||||
HRESULT CDefView::OpenSelectedItems()
|
HRESULT CDefView::OpenSelectedItems()
|
||||||
{
|
{
|
||||||
HMENU hMenu;
|
HMENU hMenu;
|
||||||
CMINVOKECOMMANDINFO cmi;
|
|
||||||
UINT uCommand;
|
UINT uCommand;
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
|
|
||||||
|
@ -1287,12 +1305,7 @@ HRESULT CDefView::OpenSelectedItems()
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(&cmi, sizeof(cmi));
|
InvokeContextMenuCommand(uCommand);
|
||||||
cmi.cbSize = sizeof(cmi);
|
|
||||||
cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
|
|
||||||
cmi.hwnd = m_hWnd;
|
|
||||||
|
|
||||||
hResult = m_pCM->InvokeCommand(&cmi);
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
|
@ -1314,7 +1327,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
|
||||||
WORD y;
|
WORD y;
|
||||||
UINT uCommand;
|
UINT uCommand;
|
||||||
HMENU hMenu;
|
HMENU hMenu;
|
||||||
CMINVOKECOMMANDINFO cmi;
|
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
|
|
||||||
// for some reason I haven't figured out, we sometimes recurse into this method
|
// 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))
|
if (FAILED( hResult))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (m_FolderSettings.fFlags & FWF_DESKTOP)
|
|
||||||
SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
|
|
||||||
|
|
||||||
uCommand = TrackPopupMenu(hMenu,
|
uCommand = TrackPopupMenu(hMenu,
|
||||||
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
|
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
|
||||||
x, y, 0, m_hWnd, NULL);
|
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)
|
if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
ZeroMemory(&cmi, sizeof(cmi));
|
InvokeContextMenuCommand(uCommand);
|
||||||
cmi.cbSize = sizeof(cmi);
|
|
||||||
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
|
|
||||||
cmi.hwnd = m_hWnd;
|
|
||||||
m_pCM->InvokeCommand(&cmi);
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
if (m_pCM)
|
if (m_pCM)
|
||||||
m_pCM.Release();
|
m_pCM.Release();
|
||||||
|
|
||||||
|
@ -1372,7 +1376,6 @@ cleanup:
|
||||||
LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
|
LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
|
||||||
{
|
{
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
CMINVOKECOMMANDINFO cmi;
|
|
||||||
HMENU hMenu;
|
HMENU hMenu;
|
||||||
|
|
||||||
hMenu = CreatePopupMenu();
|
hMenu = CreatePopupMenu();
|
||||||
|
@ -1387,14 +1390,9 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
|
||||||
if (FAILED( hResult))
|
if (FAILED( hResult))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
ZeroMemory(&cmi, sizeof(cmi));
|
InvokeContextMenuCommand(uCommand);
|
||||||
cmi.cbSize = sizeof(cmi);
|
|
||||||
cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
|
|
||||||
cmi.hwnd = m_hWnd;
|
|
||||||
m_pCM->InvokeCommand(&cmi);
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
if (m_pCM)
|
if (m_pCM)
|
||||||
m_pCM.Release();
|
m_pCM.Release();
|
||||||
|
|
||||||
|
|
|
@ -1165,19 +1165,9 @@ CDefaultContextMenu::DoCreateLink(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) {
|
HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
|
||||||
TRACE("(%p) Deleting\n", this);
|
{
|
||||||
|
DoDeleteAsync(m_pDataObj, lpcmi->fMask);
|
||||||
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;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1030,10 +1030,14 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
|
||||||
InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
|
InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
|
||||||
|
|
||||||
/* Handle cfShellIDList Drop objects here, otherwise send the approriate message to other software */
|
/* Handle cfShellIDList Drop objects here, otherwise send the approriate message to other software */
|
||||||
if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) {
|
if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
|
||||||
IStream *s;
|
{
|
||||||
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
|
DWORD fMask = 0;
|
||||||
SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
|
|
||||||
|
if ((dwKeyState & MK_SHIFT) == MK_SHIFT)
|
||||||
|
fMask |= CMIC_MASK_SHIFT_DOWN;
|
||||||
|
|
||||||
|
DoDeleteAsync(pDataObject, fMask);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1045,20 +1049,7 @@ HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter)
|
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda, DWORD fMask)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
TRACE("performing delete");
|
TRACE("performing delete");
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -1160,7 +1151,8 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
|
||||||
ZeroMemory(&FileOp, sizeof(FileOp));
|
ZeroMemory(&FileOp, sizeof(FileOp));
|
||||||
FileOp.wFunc = FO_DELETE;
|
FileOp.wFunc = FO_DELETE;
|
||||||
FileOp.pFrom = pwszPaths;
|
FileOp.pFrom = pwszPaths;
|
||||||
FileOp.fFlags = FOF_ALLOWUNDO;
|
if ((fMask & CMIC_MASK_SHIFT_DOWN) == 0)
|
||||||
|
FileOp.fFlags = FOF_ALLOWUNDO;
|
||||||
|
|
||||||
if (SHFileOperationW(&FileOp) != 0)
|
if (SHFileOperationW(&FileOp) != 0)
|
||||||
{
|
{
|
||||||
|
@ -1176,6 +1168,35 @@ HRESULT WINAPI DoDeleteDataObject(IDataObject *pda)
|
||||||
return hr;
|
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.@)
|
* SHEmptyRecycleBinA (SHELL32.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
#ifndef _SHFLDR_RECYCLEBIN_H_
|
#ifndef _SHFLDR_RECYCLEBIN_H_
|
||||||
#define _SHFLDR_RECYCLEBIN_H_
|
#define _SHFLDR_RECYCLEBIN_H_
|
||||||
|
|
||||||
DWORD WINAPI DoDeleteThreadProc(LPVOID lpParameter);
|
void DoDeleteAsync(IDataObject *pda, DWORD fMask);
|
||||||
HRESULT WINAPI DoDeleteDataObject(IDataObject *pda);
|
|
||||||
|
|
||||||
BOOL TRASH_CanTrashFile(LPCWSTR wszPath);
|
BOOL TRASH_CanTrashFile(LPCWSTR wszPath);
|
||||||
BOOL TRASH_TrashFile(LPCWSTR wszPath);
|
BOOL TRASH_TrashFile(LPCWSTR wszPath);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue