From: Alistair Leslie-Hughes Subject: [PATCH 3/7] shell32: Implement insert/paste for item context menus. Message-Id: Date: Fri, 25 May 2018 04:49:53 +0000 In-Reply-To: <1527223779-15319-1-git-send-email-leslie_alistair@hotmail.com> References: <1527223779-15319-1-git-send-email-leslie_alistair@hotmail.com> From: Michael Müller Signed-off-by: Alistair Leslie-Hughes --- dlls/shell32/shell32.rc | 1 + dlls/shell32/shlview_cmenu.c | 64 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc index 084b052..f885b7c 100644 --- a/dlls/shell32/shell32.rc +++ b/dlls/shell32/shell32.rc @@ -99,6 +99,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "C&ut", FCIDM_SHVIEW_CUT MENUITEM "&Copy", FCIDM_SHVIEW_COPY + MENUITEM "&Paste", FCIDM_SHVIEW_INSERT MENUITEM SEPARATOR MENUITEM "Create &Link", FCIDM_SHVIEW_CREATELINK MENUITEM "&Delete", FCIDM_SHVIEW_DELETE diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c index 42770c7..c9b2ebf 100644 --- a/dlls/shell32/shlview_cmenu.c +++ b/dlls/shell32/shlview_cmenu.c @@ -64,6 +64,8 @@ typedef struct BOOL desktop; } ContextMenu; +static BOOL DoPaste(ContextMenu *This); + static inline ContextMenu *impl_from_IContextMenu3(IContextMenu3 *iface) { return CONTAINING_RECORD(iface, ContextMenu, IContextMenu3_iface); @@ -142,6 +144,30 @@ static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface) return ref; } +static BOOL CheckClipboard(void) +{ + IDataObject *pda; + BOOL ret = FALSE; + + if (SUCCEEDED(OleGetClipboard(&pda))) + { + STGMEDIUM medium; + FORMATETC formatetc; + + /* Set the FORMATETC structure*/ + InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL); + + /* Get the pidls from IDataObject */ + if (SUCCEEDED(IDataObject_GetData(pda, &formatetc, &medium))) + { + ReleaseStgMedium(&medium); + ret = TRUE; + } + IDataObject_Release(pda); + } + return ret; +} + static HRESULT WINAPI ItemMenu_QueryContextMenu( IContextMenu3 *iface, HMENU hmenu, @@ -152,6 +178,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( { ContextMenu *This = impl_from_IContextMenu3(iface); INT uIDMax; + DWORD attr = SFGAO_CANRENAME; TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); @@ -188,6 +215,9 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); + if (This->apidl && This->cidl == 1) + IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr); + if(uFlags & ~CMF_CANRENAME) RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND); else @@ -198,16 +228,14 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( if (!This->apidl || This->cidl > 1) enable |= MFS_DISABLED; else - { - DWORD attr = SFGAO_CANRENAME; - - IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr); enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED; - } EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, enable); } + if ((attr & (SFGAO_FILESYSTEM|SFGAO_FOLDER)) != (SFGAO_FILESYSTEM|SFGAO_FOLDER) || !CheckClipboard()) + RemoveMenu(hmenu, FCIDM_SHVIEW_INSERT + idCmdFirst, MF_BYCOMMAND); + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst); } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); @@ -780,6 +808,10 @@ static HRESULT WINAPI ItemMenu_InvokeCommand( TRACE("Verb FCIDM_SHVIEW_CUT\n"); DoCopyOrCut(This, lpcmi->hwnd, TRUE); break; + case FCIDM_SHVIEW_INSERT: + TRACE("Verb FCIDM_SHVIEW_INSERT\n"); + DoPaste(This); + break; case FCIDM_SHVIEW_PROPERTIES: TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n"); DoOpenProperties(This, lpcmi->hwnd); @@ -811,6 +843,7 @@ static HRESULT WINAPI ItemMenu_GetCommandString(IContextMenu3 *iface, UINT_PTR c static const WCHAR exploreW[] = {'e','x','p','l','o','r','e',0}; static const WCHAR cutW[] = {'c','u','t',0}; static const WCHAR copyW[] = {'c','o','p','y',0}; + static const WCHAR pasteW[] = {'p','a','s','t','e',0}; static const WCHAR linkW[] = {'l','i','n','k',0}; static const WCHAR deleteW[] = {'d','e','l','e','t','e',0}; static const WCHAR propertiesW[] = {'p','r','o','p','e','r','t','i','e','s',0}; @@ -844,6 +877,9 @@ static HRESULT WINAPI ItemMenu_GetCommandString(IContextMenu3 *iface, UINT_PTR c case FCIDM_SHVIEW_COPY: cmdW = copyW; break; + case FCIDM_SHVIEW_INSERT: + cmdW = pasteW; + break; case FCIDM_SHVIEW_CREATELINK: cmdW = linkW; break; @@ -1142,8 +1178,22 @@ static BOOL DoPaste(ContextMenu *This) if (psfFrom) { /* get source and destination shellfolder */ - ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); + ISFHelper *psfhlpdst = NULL, *psfhlpsrc = NULL; + + /* when using an item context menu we first need to bind to the selected folder */ + if (This->apidl) + { + IShellFolder *folder; + + if (SUCCEEDED(IShellFolder_BindToObject(This->parent, This->apidl[0], NULL, &IID_IShellFolder, (LPVOID*)&folder))) + { + IShellFolder_QueryInterface(folder, &IID_ISFHelper, (void**)&psfhlpdst); + IShellFolder_Release(folder); + } + } + else + IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); + IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc); /* do the copy/move */ -- 1.9.1