- 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
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 ***
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;
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:
WORD y;
UINT uCommand;
HMENU hMenu;
- CMINVOKECOMMANDINFO cmi;
HRESULT hResult;
// for some reason I haven't figured out, we sometimes recurse into this method
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);
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();
LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
{
HRESULT hResult;
- CMINVOKECOMMANDINFO cmi;
HMENU hMenu;
hMenu = CreatePopupMenu();
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();
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;
}
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
{
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;
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)
{
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.@)
*/
#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);