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/explore…
==============================================================================
--- 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/explore…
==============================================================================
--- 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()
};