Author: gadamopoulos Date: Tue Jul 26 15:09:04 2016 New Revision: 72004
URL: http://svn.reactos.org/svn/reactos?rev=72004&view=rev Log: [BROWSEUI] - CExplorerBand: Implement showing the context menu on right click. - Part of the work submitted by Sylvain Deverre. CORE-10838
Modified: trunk/reactos/dll/win32/browseui/explorerband.cpp trunk/reactos/dll/win32/browseui/explorerband.h
Modified: trunk/reactos/dll/win32/browseui/explorerband.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/explorer... ============================================================================== --- trunk/reactos/dll/win32/browseui/explorerband.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/browseui/explorerband.cpp [iso-8859-1] Tue Jul 26 15:09:04 2016 @@ -142,6 +142,33 @@ return reinterpret_cast<NodeInfo*>(tvItem.lParam); }
+HRESULT CExplorerBand::ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd) +{ + CComPtr<IOleWindow> pBrowserOleWnd; + CMINVOKECOMMANDINFO cmi; + HWND browserWnd; + HRESULT hr; + + hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IOleWindow, &pBrowserOleWnd)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = pBrowserOleWnd->GetWindow(&browserWnd); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + ZeroMemory(&cmi, sizeof(cmi)); + cmi.cbSize = sizeof(cmi); + cmi.lpVerb = MAKEINTRESOURCEA(nCmd); + cmi.hwnd = browserWnd; + if (GetKeyState(VK_SHIFT) & 0x8000) + cmi.fMask |= CMIC_MASK_SHIFT_DOWN; + if (GetKeyState(VK_CONTROL) & 0x8000) + cmi.fMask |= CMIC_MASK_CONTROL_DOWN; + + return menu->InvokeCommand(&cmi); +} + HRESULT CExplorerBand::UpdateBrowser(LPITEMIDLIST pidlGoto) { CComPtr<IShellBrowser> pBrowserService; @@ -197,17 +224,111 @@ { NodeInfo* pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
- UpdateBrowser(pNodeInfo->absolutePidl); - /* Prevents navigation if selection is initiated inside the band */ if (bNavigating) return;
+ UpdateBrowser(pNodeInfo->absolutePidl); + SetFocus(); // Expand the node //TreeView_Expand(m_hWnd, pnmtv->itemNew.hItem, TVE_EXPAND); }
+ +// *** ATL event handlers *** +LRESULT CExplorerBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + HTREEITEM item; + NodeInfo *info; + HMENU treeMenu; + WORD x; + WORD y; + CComPtr<IShellFolder> pFolder; + CComPtr<IContextMenu> contextMenu; + HRESULT hr; + UINT uCommand; + LPITEMIDLIST pidlChild; + + treeMenu = NULL; + item = TreeView_GetSelection(m_hWnd); + bHandled = TRUE; + if (!item) + { + goto Cleanup; + } + + x = LOWORD(lParam); + y = HIWORD(lParam); + if (x == -1 && y == -1) + { + // TODO: grab position of tree item and position it correctly + } + + info = GetNodeInfo(item); + if (!info) + { + ERR("No node data, something has gone wrong !\n"); + goto Cleanup; + } + hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, &pFolder), + (LPCITEMIDLIST*)&pidlChild); + if (!SUCCEEDED(hr)) + { + ERR("Can't bind to folder!\n"); + goto Cleanup; + } + hr = pFolder->GetUIObjectOf(m_hWnd, 1, (LPCITEMIDLIST*)&pidlChild, IID_IContextMenu, + NULL, reinterpret_cast<void**>(&contextMenu)); + if (!SUCCEEDED(hr)) + { + ERR("Can't get IContextMenu interface\n"); + goto Cleanup; + } + treeMenu = CreatePopupMenu(); + hr = contextMenu->QueryContextMenu(treeMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, + CMF_EXPLORE); + if (!SUCCEEDED(hr)) + { + WARN("Can't get context menu for item\n"); + DestroyMenu(treeMenu); + goto Cleanup; + } + uCommand = TrackPopupMenu(treeMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, + x, y, 0, m_hWnd, NULL); + + ExecuteCommand(contextMenu, uCommand); +Cleanup: + if (treeMenu) + DestroyMenu(treeMenu); + bNavigating = TRUE; + TreeView_SelectItem(m_hWnd, oldSelected); + bNavigating = FALSE; + return TRUE; +} + +LRESULT CExplorerBand::ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + bHandled = FALSE; + if (uMsg == WM_RBUTTONDOWN) + { + TVHITTESTINFO info; + info.pt.x = LOWORD(lParam); + info.pt.y = HIWORD(lParam); + info.flags = TVHT_ONITEM; + info.hItem = NULL; + + // Save the current location + oldSelected = TreeView_GetSelection(m_hWnd); + + // Move to the item selected by the treeview (don't change right pane) + TreeView_HitTest(m_hWnd, &info); + bNavigating = TRUE; + TreeView_SelectItem(m_hWnd, info.hItem); + bNavigating = FALSE; + } + return FALSE; /* let the wndproc process the message */ +} // *** Helper functions *** HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort) { @@ -723,6 +844,7 @@ // *** IWinEventHandler methods *** HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) { + BOOL bHandled; if (uMsg == WM_NOTIFY) { NMHDR *pNotifyHeader = (NMHDR*)lParam; @@ -734,6 +856,74 @@ case TVN_SELCHANGED: OnSelectionChanged((LPNMTREEVIEW)lParam); break; + case NM_RCLICK: + OnContextMenu(WM_CONTEXTMENU, (WPARAM)m_hWnd, GetMessagePos(), bHandled); + *theResult = 1; + break; + case TVN_BEGINLABELEDITW: + { + // TODO: put this in a function ? (mostly copypasta from CDefView) + DWORD dwAttr = SFGAO_CANRENAME; + LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam; + CComPtr<IShellFolder> pParent; + LPCITEMIDLIST pChild; + HRESULT hr; + + *theResult = 1; + NodeInfo *info = GetNodeInfo(dispInfo->item.hItem); + if (!info) + return E_FAIL; + hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, &pParent), &pChild); + if (!SUCCEEDED(hr) || !pParent.p) + return E_FAIL; + + hr = pParent->GetAttributesOf(1, &pChild, &dwAttr); + if (SUCCEEDED(hr) && (dwAttr & SFGAO_CANRENAME)) + *theResult = 0; + return S_OK; + } + case TVN_ENDLABELEDITW: + { + LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam; + NodeInfo *info = GetNodeInfo(dispInfo->item.hItem); + HRESULT hr; + + *theResult = 0; + if (dispInfo->item.pszText) + { + LPITEMIDLIST pidlNew; + CComPtr<IShellFolder> pParent; + LPCITEMIDLIST pidlChild; + + hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, &pParent), &pidlChild); + if (!SUCCEEDED(hr) || !pParent.p) + return E_FAIL; + + hr = pParent->SetNameOf(0, pidlChild, dispInfo->item.pszText, SHGDN_INFOLDER, &pidlNew); + if(SUCCEEDED(hr) && pidlNew) + { + CComPtr<IPersistFolder2> pPersist; + LPITEMIDLIST pidlParent, pidlNewAbs; + + hr = pParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pPersist)); + if(!SUCCEEDED(hr)) + return E_FAIL; + + hr = pPersist->GetCurFolder(&pidlParent); + if(!SUCCEEDED(hr)) + return E_FAIL; + pidlNewAbs = ILCombine(pidlParent, pidlNew); + + // Navigate to our new location + UpdateBrowser(pidlNewAbs); + + ILFree(pidlNewAbs); + ILFree(pidlNew); + *theResult = 1; + } + return S_OK; + } + } default: break; }
Modified: trunk/reactos/dll/win32/browseui/explorerband.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/explorer... ============================================================================== --- trunk/reactos/dll/win32/browseui/explorerband.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/browseui/explorerband.h [iso-8859-1] Tue Jul 26 15:09:04 2016 @@ -61,6 +61,7 @@ DWORD dwBandID; HIMAGELIST hImageList; HTREEITEM hRoot; + HTREEITEM oldSelected;
// *** notification cookies *** DWORD adviseCookie; @@ -68,9 +69,14 @@
void InitializeExplorerBand(); void DestroyExplorerBand(); + HRESULT ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd);
BOOL OnTreeItemExpanding(LPNMTREEVIEW pnmtv); void OnSelectionChanged(LPNMTREEVIEW pnmtv); + + // *** ATL event handlers *** + LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
// *** Helper functions *** NodeInfo* GetNodeInfo(HTREEITEM hItem); @@ -141,7 +147,7 @@ virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo); virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId); virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr); - + // *** IDropTarget methods *** virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pObj, DWORD glfKeyState, POINTL pt, DWORD *pdwEffect); virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect); @@ -174,6 +180,8 @@ END_COM_MAP()
BEGIN_MSG_MAP(CExplorerBand) + MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) + MESSAGE_HANDLER(WM_RBUTTONDOWN, ContextMenuHack) END_MSG_MAP() };