generic support for owner drawn context menus
authorMartin Fuchs <fuchs.martin@gmail.com>
Sun, 6 Feb 2005 13:02:48 +0000 (13:02 +0000)
committerMartin Fuchs <fuchs.martin@gmail.com>
Sun, 6 Feb 2005 13:02:48 +0000 (13:02 +0000)
svn path=/trunk/; revision=13437

20 files changed:
reactos/subsys/system/explorer/desktop/desktop.cpp
reactos/subsys/system/explorer/desktop/desktop.h
reactos/subsys/system/explorer/doc/TODO.txt
reactos/subsys/system/explorer/shell/entries.cpp
reactos/subsys/system/explorer/shell/entries.h
reactos/subsys/system/explorer/shell/filechild.cpp
reactos/subsys/system/explorer/shell/filechild.h
reactos/subsys/system/explorer/shell/mainframe.cpp
reactos/subsys/system/explorer/shell/mainframe.h
reactos/subsys/system/explorer/shell/pane.cpp
reactos/subsys/system/explorer/shell/shellbrowser.cpp
reactos/subsys/system/explorer/shell/shellbrowser.h
reactos/subsys/system/explorer/shell/shellfs.cpp
reactos/subsys/system/explorer/shell/shellfs.h
reactos/subsys/system/explorer/taskbar/quicklaunch.cpp
reactos/subsys/system/explorer/taskbar/quicklaunch.h
reactos/subsys/system/explorer/taskbar/startmenu.cpp
reactos/subsys/system/explorer/taskbar/startmenu.h
reactos/subsys/system/explorer/utility/shellclasses.cpp
reactos/subsys/system/explorer/utility/shellclasses.h

index 321de23..2df46e2 100644 (file)
@@ -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);
index 599c7cb..751ffe4 100644 (file)
@@ -165,9 +165,9 @@ public:
 
 
  /// subclassed ShellView window
-struct DesktopShellView : public SubclassedWindow
+struct DesktopShellView : public ExtContextMenuHandlerT<SubclassedWindow>
 {
-       typedef SubclassedWindow super;
+       typedef ExtContextMenuHandlerT<SubclassedWindow> 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
 };
index 905cbb0..06d29af 100644 (file)
@@ -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
 
index cb00870..4f12f01 100644 (file)
@@ -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);
        }
 }
 
index a1861ec..4999108 100644 (file)
@@ -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);
 };
 
 
index 3cedc01..5861655 100644 (file)
@@ -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;}
 
index d5d0721..a81ea0d 100644 (file)
@@ -85,9 +85,9 @@ struct WebChildWndInfo : public FileChildWndInfo
 
 
  /// MDI child window displaying file lists
-struct FileChildWindow : public ChildWindow
+struct FileChildWindow : public ExtContextMenuHandlerT<ChildWindow>
 {
-       typedef ChildWindow super;
+       typedef ExtContextMenuHandlerT<ChildWindow> super;
 
        FileChildWindow(HWND hwnd, const FileChildWndInfo& info);
 
index fadbec1..10699aa 100644 (file)
@@ -1564,7 +1564,7 @@ void SDIMainFrame::update_shell_browser()
        }
 
        _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
-                                                                                               _shellpath_info, _himlSmall, this));
+                                                                                               _shellpath_info, _himlSmall, this, _cm_ifs));
 
        _shellBrowser->Init(_hwnd);
 
index a41d650..5cdc320 100644 (file)
@@ -124,9 +124,13 @@ protected:
 #endif
 
 
-struct SDIMainFrame : public ShellBrowserChildT<MainFrameBase>
+struct SDIMainFrame : public ExtContextMenuHandlerT<
+                               ShellBrowserChildT<MainFrameBase>
+                       >
 {
-       typedef ShellBrowserChildT<MainFrameBase> super;
+       typedef ExtContextMenuHandlerT<
+                               ShellBrowserChildT<MainFrameBase>
+                       > super;
 
        SDIMainFrame(HWND hwnd);
 
index 079dc0d..9753799 100644 (file)
@@ -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(""));
        }
 }
 
index 3f958eb..91a4dd4 100644 (file)
 #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<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
-                                                                                               _shellpath_info, _himlSmall, this));
+                                                                                               _shellpath_info, _himlSmall, this, _cm_ifs));
 
        _shellBrowser->Init(_hwndFrame);
 }
index 18360e9..d256a6b 100644 (file)
@@ -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<ChildWindow>
+struct MDIShellBrowserChild : public ExtContextMenuHandlerT<
+                               ShellBrowserChildT<ChildWindow>
+                       >
 {
-       typedef ShellBrowserChildT<ChildWindow> super;
+       typedef ExtContextMenuHandlerT<
+                               ShellBrowserChildT<ChildWindow>
+                       > super;
 
        MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info);
 
index 49748a7..d636097 100644 (file)
@@ -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<ShellDirectory*>(_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);
 }
 
 
index dd5576f..9f8276d 100644 (file)
@@ -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;
 
index 529324c..464ab3a 100644 (file)
@@ -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;}
index ff1230c..f50b4d9 100644 (file)
@@ -57,9 +57,9 @@ struct QuickLaunchMap : public map<int, QuickLaunchEntry>
 
 
  /// quick launch bar window
-struct QuickLaunchBar : public SubclassedWindow
+struct QuickLaunchBar : public ExtContextMenuHandlerT<SubclassedWindow>
 {
-       typedef SubclassedWindow super;
+       typedef ExtContextMenuHandlerT<SubclassedWindow> super;
 
        QuickLaunchBar(HWND hwnd);
        ~QuickLaunchBar();
index 70befc5..d630b8b 100644 (file)
@@ -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
                                }
                        }
index fb2a9e7..21bb72d 100644 (file)
@@ -202,15 +202,15 @@ extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON
  */
 struct StartMenu :
 #ifdef _LIGHT_STARTMENU
-       public OwnerDrawParent<Window>
+       public ExtContextMenuHandlerT<OwnerDrawParent<Window> >
 #else
-       public OwnerDrawParent<DialogWindow>
+       public ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> >
 #endif
 {
 #ifdef _LIGHT_STARTMENU
-       typedef OwnerDrawParent<Window> super;
+       typedef ExtContextMenuHandlerT<OwnerDrawParent<Window> > super;
 #else
-       typedef OwnerDrawParent<DialogWindow> super;
+       typedef ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> > super;
 #endif
 
        StartMenu(HWND hwnd);
index 4b999d9..fdc4773 100644 (file)
@@ -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;
 
index f3e66a4..0e1f6ff 100644 (file)
@@ -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<typename BASE> struct ExtContextMenuHandlerT
+ : public BASE
+{
+       typedef BASE super;
+
+       ExtContextMenuHandlerT(HWND hwnd)
+        :      super(hwnd)
+       {
+       }
+
+       template<typename PARA> 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);