diff --git a/reactos/subsys/system/explorer/desktop/desktop.cpp b/reactos/subsys/system/explorer/desktop/desktop.cpp index 19e340c9e85..613dffb1094 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.cpp +++ b/reactos/subsys/system/explorer/desktop/desktop.cpp @@ -439,11 +439,11 @@ bool DesktopShellView::InitDragDrop() return true; } -LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_CONTEXTMENU: - if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) + if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam), _cm_ifs)) DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); break; @@ -467,7 +467,7 @@ int DesktopShellView::Notify(int id, NMHDR* pnmh) return super::Notify(id, pnmh); } -bool DesktopShellView::DoContextMenu(int x, int y) +bool DesktopShellView::DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs) { IDataObject* selection; @@ -497,7 +497,7 @@ bool DesktopShellView::DoContextMenu(int x, int y) for(int i=pida->cidl; i>0; --i) apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]); - hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y); + hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, cm_ifs); selection->Release(); @@ -513,6 +513,8 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm); if (SUCCEEDED(hr)) { + pcm = _cm_ifs.query_interfaces(pcm); + HMENU hmenu = CreatePopupMenu(); if (hmenu) { @@ -524,6 +526,8 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL); + _cm_ifs.reset(); + if (idCmd == FCIDM_SHVIEWLAST-1) { explorer_about(_hwnd); } else if (idCmd) { diff --git a/reactos/subsys/system/explorer/desktop/desktop.h b/reactos/subsys/system/explorer/desktop/desktop.h index e39b0515cc4..cf358455d57 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.h +++ b/reactos/subsys/system/explorer/desktop/desktop.h @@ -163,9 +163,9 @@ public: /// subclassed ShellView window -struct DesktopShellView : public SubclassedWindow +struct DesktopShellView : public ExtContextMenuHandlerT { - typedef SubclassedWindow super; + typedef ExtContextMenuHandlerT super; DesktopShellView(HWND hwnd, IShellView* pShellView); @@ -178,7 +178,7 @@ protected: int Command(int id, int code); int Notify(int id, NMHDR* pnmh); - bool DoContextMenu(int x, int y); + bool DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs); HRESULT DoDesktopContextMenu(int x, int y); DesktopDropTarget* _pDropTarget; diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index a2eedaf350d..77267841d19 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -103,7 +103,7 @@ void MainFrame::update_explorer_view() } } - _shellBrowser = auto_ptr(new ShellBrowserChild(_hwnd, _left_hwnd, _right_hwnd, _create_info)); + _shellBrowser = auto_ptr(new ShellBrowserChild(_hwnd, _left_hwnd, _right_hwnd, _create_info, _cm_ifs)); // update _shellBrowser->_clnt_rect ClientRect rect(_hwnd); diff --git a/reactos/subsys/system/explorer/shell/mainframe.h b/reactos/subsys/system/explorer/shell/mainframe.h index 9752281c0da..272c132b9c0 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.h +++ b/reactos/subsys/system/explorer/shell/mainframe.h @@ -31,9 +31,9 @@ enum OPEN_WINDOW_MODE {OWM_EXPLORE=1, OWM_DETAILS=2, OWM_PIDL=4}; /// Explorer frame window -struct MainFrame : public PreTranslateWindow +struct MainFrame : public ExtContextMenuHandlerT { - typedef PreTranslateWindow super; + typedef ExtContextMenuHandlerT super; MainFrame(HWND hwnd); ~MainFrame(); diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.cpp b/reactos/subsys/system/explorer/shell/shellbrowser.cpp index 87382f88ba2..2401d0d009f 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.cpp +++ b/reactos/subsys/system/explorer/shell/shellbrowser.cpp @@ -45,11 +45,13 @@ static LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem) } -ShellBrowserChild::ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info) +ShellBrowserChild::ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, + ShellPathInfo& create_info, CtxMenuInterfaces& cm_ifs) : _hwnd(hwnd), _left_hwnd(left_hwnd), _right_hwnd(right_hwnd), - _create_info(create_info) + _create_info(create_info), + _cm_ifs(_cm_ifs) { _pShellView = NULL; _pDropTarget = NULL; @@ -212,13 +214,13 @@ void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPO ShellFolder folder = dir? dir->_folder: GetDesktopFolder(); LPCITEMIDLIST pidl = static_cast(entry)->_pidl; - CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y)); + CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y, _cm_ifs)); } else { ShellPath shell_path = entry->create_absolute_pidl(); LPCITEMIDLIST pidl = shell_path; ///@todo use parent folder instead of desktop - CHECKERROR(ShellFolderContextMenu(GetDesktopFolder(), _hwnd, 1, &pidl, pptScreen->x, pptScreen->y)); + CHECKERROR(ShellFolderContextMenu(GetDesktopFolder(), _hwnd, 1, &pidl, pptScreen->x, pptScreen->y, _cm_ifs)); } } } @@ -229,6 +231,8 @@ void ShellBrowserChild::OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh) LPNMTVDISPINFO lpdi = (LPNMTVDISPINFO)pnmh; ShellEntry* entry = (ShellEntry*)lpdi->item.lParam; + if (!entry) + return; if (lpdi->item.mask & TVIF_TEXT) lpdi->item.pszText = entry->_display_name; diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.h b/reactos/subsys/system/explorer/shell/shellbrowser.h index 652508b6424..b0aa8333e99 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.h +++ b/reactos/subsys/system/explorer/shell/shellbrowser.h @@ -44,7 +44,8 @@ struct ShellPathInfo /// Implementation of IShellBrowserImpl interface in explorer child windows struct ShellBrowserChild : public IShellBrowserImpl { - ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info); + ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, + ShellPathInfo& create_info, CtxMenuInterfaces& cm_ifs); virtual ~ShellBrowserChild(); //IOleWindow @@ -152,4 +153,5 @@ public: protected: ShellDirectory* _cur_dir; + CtxMenuInterfaces& _cm_ifs; }; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.cpp b/reactos/subsys/system/explorer/utility/shellclasses.cpp index 37545840fa2..b1fc81e5d5d 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.cpp +++ b/reactos/subsys/system/explorer/utility/shellclasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -468,7 +468,56 @@ SpecialFolderFSPath::SpecialFolderFSPath(int folder, HWND hwnd) } -HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* apidl, int x, int y) +void CtxMenuInterfaces::reset() +{ + _pctxmenu2 = NULL; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + _pctxmenu3 = NULL; +#endif +} + +bool CtxMenuInterfaces::HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + if (_pctxmenu3) { + if (SUCCEEDED(_pctxmenu3->HandleMenuMsg(nmsg, wparam, lparam))) + return true; + } +#endif + + if (_pctxmenu2) + if (SUCCEEDED(_pctxmenu2->HandleMenuMsg(nmsg, wparam, lparam))) + return true; + + return false; +} + +IContextMenu* CtxMenuInterfaces::query_interfaces(IContextMenu* pcm1) +{ + IContextMenu* pcm = NULL; + + reset(); + + // Get the higher version context menu interfaces. +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + if (pcm1->QueryInterface(IID_IContextMenu3, (void**)&pcm) == NOERROR) + _pctxmenu3 = (LPCONTEXTMENU3)pcm; + else +#endif + if (pcm1->QueryInterface (IID_IContextMenu2, (void**)&pcm) == NOERROR) + _pctxmenu2 = (LPCONTEXTMENU2)pcm; + + if (pcm) { + pcm1->Release(); + return pcm; + } else + return pcm1; +} + + +HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, + LPCITEMIDLIST* apidl, int x, int y, CtxMenuInterfaces& cm_ifs) { IContextMenu* pcm; @@ -476,6 +525,8 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int // HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); if (SUCCEEDED(hr)) { + pcm = cm_ifs.query_interfaces(pcm); + HMENU hmenu = CreatePopupMenu(); if (hmenu) { @@ -484,6 +535,8 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int if (SUCCEEDED(hr)) { UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL); + cm_ifs.reset(); + if (idCmd) { CMINVOKECOMMANDINFO cmi; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.h b/reactos/subsys/system/explorer/utility/shellclasses.h index cb7dae0e302..bb874edcf1d 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.h +++ b/reactos/subsys/system/explorer/utility/shellclasses.h @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1007,4 +1007,77 @@ protected: LPIDA _pIDList; }; -extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* ppidl, int x, int y); + +struct CtxMenuInterfaces +{ + CtxMenuInterfaces() + { + reset(); + } + + void reset(); + bool HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam); + IContextMenu* query_interfaces(IContextMenu* pcm1); + + IContextMenu2* _pctxmenu2; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + IContextMenu3* _pctxmenu3; +#endif +}; + +template struct ExtContextMenuHandlerT + : public BASE +{ + typedef BASE super; + + ExtContextMenuHandlerT(HWND hwnd) + : super(hwnd) + { + } + + template ExtContextMenuHandlerT(HWND hwnd, const PARA& info) + : super(hwnd, info) + { + } + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case WM_DRAWITEM: + case WM_MEASUREITEM: + if (!wparam) // Is the message menu-related? + if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam)) + return TRUE; + + break; + + case WM_INITMENUPOPUP: + if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam)) + return 0; + + break; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + case WM_MENUCHAR: // only supported by IContextMenu3 + if (_cm_ifs._pctxmenu3) { + LRESULT lResult = 0; + + _cm_ifs._pctxmenu3->HandleMenuMsg2(nmsg, wparam, lparam, &lResult); + + return lResult; + } + + return 0; +#endif + } + + return super::WndProc(nmsg, wparam, lparam); + } + +protected: + CtxMenuInterfaces _cm_ifs; +}; + +extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, + LPCITEMIDLIST* ppidl, int x, int y, CtxMenuInterfaces& cm_ifs);