From ac1bda4c72e4f127e44753a6dd1ced7eff39db8b Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Sun, 6 Feb 2005 13:02:48 +0000 Subject: [PATCH] generic support for owner drawn context menus svn path=/trunk/; revision=13437 --- .../system/explorer/desktop/desktop.cpp | 64 ++------------- .../subsys/system/explorer/desktop/desktop.h | 11 +-- reactos/subsys/system/explorer/doc/TODO.txt | 3 + .../subsys/system/explorer/shell/entries.cpp | 6 +- .../subsys/system/explorer/shell/entries.h | 2 +- .../system/explorer/shell/filechild.cpp | 8 +- .../subsys/system/explorer/shell/filechild.h | 4 +- .../system/explorer/shell/mainframe.cpp | 2 +- .../subsys/system/explorer/shell/mainframe.h | 8 +- reactos/subsys/system/explorer/shell/pane.cpp | 10 +-- .../system/explorer/shell/shellbrowser.cpp | 10 ++- .../system/explorer/shell/shellbrowser.h | 13 +++- .../subsys/system/explorer/shell/shellfs.cpp | 4 +- .../subsys/system/explorer/shell/shellfs.h | 2 +- .../system/explorer/taskbar/quicklaunch.cpp | 2 +- .../system/explorer/taskbar/quicklaunch.h | 4 +- .../system/explorer/taskbar/startmenu.cpp | 2 +- .../system/explorer/taskbar/startmenu.h | 8 +- .../system/explorer/utility/shellclasses.cpp | 63 +++++++++++++-- .../system/explorer/utility/shellclasses.h | 77 ++++++++++++++++++- 20 files changed, 193 insertions(+), 110 deletions(-) diff --git a/reactos/subsys/system/explorer/desktop/desktop.cpp b/reactos/subsys/system/explorer/desktop/desktop.cpp index 321de231925..2df46e25e18 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.cpp +++ b/reactos/subsys/system/explorer/desktop/desktop.cpp @@ -473,11 +473,6 @@ DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView) : super(hwnd), _pShellView(pShellView) { - _pctxmenu2 = NULL; -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - _pctxmenu3 = NULL; -#endif - _hwndListView = ::GetNextWindow(hwnd, GW_CHILD); SetWindowStyle(_hwndListView, GetWindowStyle(_hwndListView)&~LVS_ALIGNMASK);//|LVS_ALIGNTOP|LVS_AUTOARRANGE); @@ -531,7 +526,7 @@ 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; @@ -546,36 +541,6 @@ LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) case PM_DISPLAY_VERSION: return SendMessage(_hwndListView, nmsg, wparam, lparam); -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - case WM_MENUCHAR: // only supported by IContextMenu3 - if (_pctxmenu3) { - LRESULT lResult = 0; - - _pctxmenu3->HandleMenuMsg2(nmsg, wparam, lparam, &lResult); - - return lResult; - } - break; -#endif - - case WM_DRAWITEM: - case WM_MEASUREITEM: - if (wparam) - break; // If wParam != 0 then the message is not menu-related. - - // fall through - - case WM_INITMENUPOPUP: -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - if (_pctxmenu3) - _pctxmenu3->HandleMenuMsg(nmsg, wparam, lparam); - else -#endif - if (_pctxmenu2) - _pctxmenu2->HandleMenuMsg(nmsg, wparam, lparam); - - return nmsg==WM_INITMENUPOPUP? 0: TRUE; // Inform caller that we handled WM_INITPOPUPMENU by ourself. - default: return super::WndProc(nmsg, wparam, lparam); } @@ -593,7 +558,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; @@ -623,7 +588,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(); @@ -635,27 +600,11 @@ bool DesktopShellView::DoContextMenu(int x, int y) HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) { IContextMenu* pcm1; - IContextMenu* pcm; HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm1); if (SUCCEEDED(hr)) { - // Get the higher version context menu interfaces. - _pctxmenu2 = NULL; -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - _pctxmenu3 = NULL; - - 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(); - else - pcm = pcm1; + IContextMenu* pcm = _cm_ifs.query_interfaces(pcm1); HMENU hmenu = CreatePopupMenu(); @@ -668,10 +617,7 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL); - _pctxmenu2 = NULL; -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - _pctxmenu3 = NULL; -#endif + _cm_ifs.reset(); if (idCmd == FCIDM_SHVIEWLAST-1) { explorer_about(_hwnd); diff --git a/reactos/subsys/system/explorer/desktop/desktop.h b/reactos/subsys/system/explorer/desktop/desktop.h index 599c7cb0514..751ffe4e18c 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.h +++ b/reactos/subsys/system/explorer/desktop/desktop.h @@ -165,9 +165,9 @@ public: /// subclassed ShellView window -struct DesktopShellView : public SubclassedWindow +struct DesktopShellView : public ExtContextMenuHandlerT { - typedef SubclassedWindow super; + typedef ExtContextMenuHandlerT super; DesktopShellView(HWND hwnd, IShellView* pShellView); @@ -180,16 +180,11 @@ 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); void PositionIcons(int dir=1); DesktopDropTarget* _pDropTarget; HWND _hwndListView; int _icon_algo; - - IContextMenu2* _pctxmenu2; -#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) - IContextMenu3* _pctxmenu3; -#endif }; diff --git a/reactos/subsys/system/explorer/doc/TODO.txt b/reactos/subsys/system/explorer/doc/TODO.txt index 905cbb0b077..06d29af573c 100644 --- a/reactos/subsys/system/explorer/doc/TODO.txt +++ b/reactos/subsys/system/explorer/doc/TODO.txt @@ -24,4 +24,7 @@ - hide desktop bar when showing full screen applications - new start menu entry "Filemanager" close to "Explore" -> display C: and D: drive in MDI window - Startmenu: You can open the start menu by pressing Win-key, but can't close with another hit of Win-key. +- Export von Bookmarks für IE (+ Mozilla) + +- Search Programs -> performance monitor.msv -> Abort diff --git a/reactos/subsys/system/explorer/shell/entries.cpp b/reactos/subsys/system/explorer/shell/entries.cpp index cb008704068..4f12f01e474 100644 --- a/reactos/subsys/system/explorer/shell/entries.cpp +++ b/reactos/subsys/system/explorer/shell/entries.cpp @@ -401,7 +401,7 @@ BOOL Entry::launch_entry(HWND hwnd, UINT nCmdShow) } -HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) +HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs) { ShellPath shell_path = create_absolute_pidl(); LPCITEMIDLIST pidl_abs = shell_path; @@ -419,7 +419,7 @@ HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) HRESULT hr = (*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); if (SUCCEEDED(hr)) { - hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y); + hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); parentFolder->Release(); } @@ -442,7 +442,7 @@ HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) ShellFolder parent_folder = parent_path; return ShellFolderContextMenu(parent_folder, hwnd, 1, &pidl, pos.x, pos.y); */ - return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y); + return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y, cm_ifs); } } diff --git a/reactos/subsys/system/explorer/shell/entries.h b/reactos/subsys/system/explorer/shell/entries.h index a1861ec55c4..49991084e31 100644 --- a/reactos/subsys/system/explorer/shell/entries.h +++ b/reactos/subsys/system/explorer/shell/entries.h @@ -112,7 +112,7 @@ public: virtual ShellPath create_absolute_pidl() const {return (LPCITEMIDLIST)NULL;} virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); - virtual HRESULT do_context_menu(HWND hwnd, const POINT& pos); + virtual HRESULT do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs); }; diff --git a/reactos/subsys/system/explorer/shell/filechild.cpp b/reactos/subsys/system/explorer/shell/filechild.cpp index 3cedc016301..586165581f6 100644 --- a/reactos/subsys/system/explorer/shell/filechild.cpp +++ b/reactos/subsys/system/explorer/shell/filechild.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 @@ -123,7 +123,7 @@ INT_PTR CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPA // FileChildWindow FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) - : ChildWindow(hwnd, info) + : super(hwnd, info) { CONTEXT("FileChildWindow::FileChildWindow()"); @@ -433,7 +433,7 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) if (dis->CtlID == IDW_TREE_LEFT) _left->draw_item(dis, entry); - else + else if (dis->CtlID == IDW_TREE_RIGHT) _right->draw_item(dis, entry); return TRUE;} @@ -507,7 +507,7 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) if (idx != -1) { Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx); - CHECKERROR(entry->do_context_menu(_hwnd, pt_screen)); + CHECKERROR(entry->do_context_menu(_hwnd, pt_screen, _cm_ifs)); } break;} diff --git a/reactos/subsys/system/explorer/shell/filechild.h b/reactos/subsys/system/explorer/shell/filechild.h index d5d0721424c..a81ea0ddd0e 100644 --- a/reactos/subsys/system/explorer/shell/filechild.h +++ b/reactos/subsys/system/explorer/shell/filechild.h @@ -85,9 +85,9 @@ struct WebChildWndInfo : public FileChildWndInfo /// MDI child window displaying file lists -struct FileChildWindow : public ChildWindow +struct FileChildWindow : public ExtContextMenuHandlerT { - typedef ChildWindow super; + typedef ExtContextMenuHandlerT super; FileChildWindow(HWND hwnd, const FileChildWndInfo& info); diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index fadbec1907a..10699aa7b6d 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -1564,7 +1564,7 @@ void SDIMainFrame::update_shell_browser() } _shellBrowser = auto_ptr(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd, - _shellpath_info, _himlSmall, this)); + _shellpath_info, _himlSmall, this, _cm_ifs)); _shellBrowser->Init(_hwnd); diff --git a/reactos/subsys/system/explorer/shell/mainframe.h b/reactos/subsys/system/explorer/shell/mainframe.h index a41d6508e7c..5cdc3206ce5 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.h +++ b/reactos/subsys/system/explorer/shell/mainframe.h @@ -124,9 +124,13 @@ protected: #endif -struct SDIMainFrame : public ShellBrowserChildT +struct SDIMainFrame : public ExtContextMenuHandlerT< + ShellBrowserChildT + > { - typedef ShellBrowserChildT super; + typedef ExtContextMenuHandlerT< + ShellBrowserChildT + > super; SDIMainFrame(HWND hwnd); diff --git a/reactos/subsys/system/explorer/shell/pane.cpp b/reactos/subsys/system/explorer/shell/pane.cpp index 079dc0d256c..975379939b5 100644 --- a/reactos/subsys/system/explorer/shell/pane.cpp +++ b/reactos/subsys/system/explorer/shell/pane.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 @@ -491,9 +491,9 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol) // output type/class name if (visible_cols & COL_TYPE) { if (calcWidthCol == -1) - _out_wrkr.output_text(dis, _positions, col, entry->_type_name&&entry->_type_name!=LPSTR_TEXTCALLBACK? entry->_type_name: TEXT(""), 0); + _out_wrkr.output_text(dis, _positions, col, entry->_type_name? entry->_type_name: TEXT(""), 0); else if (calcWidthCol==col || calcWidthCol==COLUMNS) - calc_width(dis, col, entry->_type_name&&entry->_type_name!=LPSTR_TEXTCALLBACK? entry->_type_name: TEXT("")); + calc_width(dis, col, entry->_type_name? entry->_type_name: TEXT("")); } ++col; @@ -623,9 +623,9 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol) // output content / symbolic link target / comment if (visible_cols & COL_CONTENT) { if (calcWidthCol == -1) - _out_wrkr.output_text(dis, _positions, col, entry->_content&&entry->_content!=LPSTR_TEXTCALLBACK? entry->_content: TEXT(""), 0); + _out_wrkr.output_text(dis, _positions, col, entry->_content? entry->_content: TEXT(""), 0); else if (calcWidthCol==col || calcWidthCol==COLUMNS) - calc_width(dis, col, entry->_content&&entry->_content!=LPSTR_TEXTCALLBACK? entry->_content: TEXT("")); + calc_width(dis, col, entry->_content? entry->_content: TEXT("")); } } diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.cpp b/reactos/subsys/system/explorer/shell/shellbrowser.cpp index 3f958eb0b57..91a4dd45e07 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.cpp +++ b/reactos/subsys/system/explorer/shell/shellbrowser.cpp @@ -31,13 +31,15 @@ #include "../explorer_intres.h" -ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, HIMAGELIST himl, BrowserCallback* cb) +ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, + HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs) : _hwnd(hwnd), _left_hwnd(left_hwnd), _right_hwnd(right_hwnd), _create_info(create_info), _himl(himl), - _callback(cb) + _callback(cb), + _cm_ifs(cm_ifs) { _pShellView = NULL; _pDropTarget = NULL; @@ -204,7 +206,7 @@ void ShellBrowser::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh) Entry* entry = (Entry*)itemData; ClientToScreen(_left_hwnd, &tvhti.pt); - CHECKERROR(entry->do_context_menu(_hwnd, tvhti.pt)); + CHECKERROR(entry->do_context_menu(_hwnd, tvhti.pt, _cm_ifs)); } } } @@ -574,7 +576,7 @@ void MDIShellBrowserChild::update_shell_browser() } _shellBrowser = auto_ptr(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd, - _shellpath_info, _himlSmall, this)); + _shellpath_info, _himlSmall, this, _cm_ifs)); _shellBrowser->Init(_hwndFrame); } diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.h b/reactos/subsys/system/explorer/shell/shellbrowser.h index 18360e9faac..d256a6b03c2 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.h +++ b/reactos/subsys/system/explorer/shell/shellbrowser.h @@ -57,7 +57,8 @@ struct BrowserCallback /// Implementation of IShellBrowserImpl interface in explorer child windows struct ShellBrowser : public IShellBrowserImpl { - ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, HIMAGELIST himl, BrowserCallback* cb); + ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, + HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs); virtual ~ShellBrowser(); //IOleWindow @@ -153,6 +154,8 @@ protected: Root _root; ShellDirectory* _cur_dir; + CtxMenuInterfaces& _cm_ifs; + void InitializeTree(HIMAGELIST himl); bool InitDragDrop(); @@ -231,9 +234,13 @@ protected: #ifndef _NO_MDI -struct MDIShellBrowserChild : public ShellBrowserChildT +struct MDIShellBrowserChild : public ExtContextMenuHandlerT< + ShellBrowserChildT + > { - typedef ShellBrowserChildT super; + typedef ExtContextMenuHandlerT< + ShellBrowserChildT + > super; MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info); diff --git a/reactos/subsys/system/explorer/shell/shellfs.cpp b/reactos/subsys/system/explorer/shell/shellfs.cpp index 49748a7f60e..d6360979dae 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.cpp +++ b/reactos/subsys/system/explorer/shell/shellfs.cpp @@ -202,14 +202,14 @@ BOOL ShellEntry::launch_entry(HWND hwnd, UINT nCmdShow) } -HRESULT ShellEntry::do_context_menu(HWND hwnd, LPPOINT pptScreen) +HRESULT ShellEntry::do_context_menu(HWND hwnd, LPPOINT pptScreen, CtxMenuInterfaces& cm_ifs) { ShellDirectory* dir = static_cast(_up); ShellFolder folder = dir? dir->_folder: GetDesktopFolder(); LPCITEMIDLIST pidl = _pidl; - return ShellFolderContextMenu(folder, hwnd, 1, &pidl, pptScreen->x, pptScreen->y); + return ShellFolderContextMenu(folder, hwnd, 1, &pidl, pptScreen->x, pptScreen->y, cm_ifs); } diff --git a/reactos/subsys/system/explorer/shell/shellfs.h b/reactos/subsys/system/explorer/shell/shellfs.h index dd5576fc68d..9f8276d18db 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.h +++ b/reactos/subsys/system/explorer/shell/shellfs.h @@ -36,7 +36,7 @@ struct ShellEntry : public Entry virtual ShellPath create_absolute_pidl() const; virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); - virtual HRESULT do_context_menu(HWND hwnd, LPPOINT pptScreen); + virtual HRESULT do_context_menu(HWND hwnd, LPPOINT pptScreen, CtxMenuInterfaces& cm_ifs); IShellFolder* get_parent_folder() const; diff --git a/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp b/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp index 529324c4187..464ab3a0826 100644 --- a/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp +++ b/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp @@ -247,7 +247,7 @@ LRESULT QuickLaunchBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) } if (entry) // entry is NULL for desktop switch buttons - CHECKERROR(entry->do_context_menu(_hwnd, screen_pt)); + CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs)); else goto def; break;} diff --git a/reactos/subsys/system/explorer/taskbar/quicklaunch.h b/reactos/subsys/system/explorer/taskbar/quicklaunch.h index ff1230ca567..f50b4d9b9d2 100644 --- a/reactos/subsys/system/explorer/taskbar/quicklaunch.h +++ b/reactos/subsys/system/explorer/taskbar/quicklaunch.h @@ -57,9 +57,9 @@ struct QuickLaunchMap : public map /// quick launch bar window -struct QuickLaunchBar : public SubclassedWindow +struct QuickLaunchBar : public ExtContextMenuHandlerT { - typedef SubclassedWindow super; + typedef ExtContextMenuHandlerT super; QuickLaunchBar(HWND hwnd); ~QuickLaunchBar(); diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index 70befc550ba..d630b8b2203 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -442,7 +442,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) Entry* entry = *it; if (entry) { - CHECKERROR(entry->do_context_menu(_hwnd, screen_pt)); // may close start menu because of focus loss + CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs)); // may close start menu because of focus loss break; ///@todo handle context menu for more than one entry } } diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index fb2a9e72666..21bb72d31af 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -202,15 +202,15 @@ extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON */ struct StartMenu : #ifdef _LIGHT_STARTMENU - public OwnerDrawParent + public ExtContextMenuHandlerT > #else - public OwnerDrawParent + public ExtContextMenuHandlerT > #endif { #ifdef _LIGHT_STARTMENU - typedef OwnerDrawParent super; + typedef ExtContextMenuHandlerT > super; #else - typedef OwnerDrawParent super; + typedef ExtContextMenuHandlerT > super; #endif StartMenu(HWND hwnd); diff --git a/reactos/subsys/system/explorer/utility/shellclasses.cpp b/reactos/subsys/system/explorer/utility/shellclasses.cpp index 4b999d97610..fdc477391e6 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 @@ -472,14 +472,65 @@ SpecialFolderFSPath::SpecialFolderFSPath(int folder, HWND hwnd) } -HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* apidl, int x, int y) +void CtxMenuInterfaces::reset() { - IContextMenu* pcm; + _pctxmenu2 = NULL; - HRESULT hr = shell_folder->GetUIObjectOf(hwndParent, cidl, apidl, IID_IContextMenu, NULL, (LPVOID*)&pcm); -// HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); +#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* pcm1; + + HRESULT hr = shell_folder->GetUIObjectOf(hwndParent, cidl, apidl, IID_IContextMenu, NULL, (LPVOID*)&pcm1); +// HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm1); if (SUCCEEDED(hr)) { + IContextMenu* pcm = cm_ifs.query_interfaces(pcm1); + HMENU hmenu = CreatePopupMenu(); if (hmenu) { @@ -488,6 +539,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 f3e66a47265..0e1f6ff7dfe 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 @@ -1003,4 +1003,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);