generic support for owner drawn context menus

svn path=/trunk/; revision=13437
This commit is contained in:
Martin Fuchs 2005-02-06 13:02:48 +00:00
parent b98bef3c5f
commit ac1bda4c72
20 changed files with 193 additions and 110 deletions

View file

@ -473,11 +473,6 @@ DesktopShellView::DesktopShellView(HWND hwnd, IShellView* pShellView)
: super(hwnd), : super(hwnd),
_pShellView(pShellView) _pShellView(pShellView)
{ {
_pctxmenu2 = NULL;
#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
_pctxmenu3 = NULL;
#endif
_hwndListView = ::GetNextWindow(hwnd, GW_CHILD); _hwndListView = ::GetNextWindow(hwnd, GW_CHILD);
SetWindowStyle(_hwndListView, GetWindowStyle(_hwndListView)&~LVS_ALIGNMASK);//|LVS_ALIGNTOP|LVS_AUTOARRANGE); 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) { switch(nmsg) {
case WM_CONTEXTMENU: 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)); DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam));
break; break;
@ -546,36 +541,6 @@ LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
case PM_DISPLAY_VERSION: case PM_DISPLAY_VERSION:
return SendMessage(_hwndListView, nmsg, wparam, lparam); 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: default:
return super::WndProc(nmsg, wparam, lparam); return super::WndProc(nmsg, wparam, lparam);
} }
@ -593,7 +558,7 @@ int DesktopShellView::Notify(int id, NMHDR* pnmh)
return super::Notify(id, 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; IDataObject* selection;
@ -623,7 +588,7 @@ bool DesktopShellView::DoContextMenu(int x, int y)
for(int i=pida->cidl; i>0; --i) for(int i=pida->cidl; i>0; --i)
apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[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(); selection->Release();
@ -635,27 +600,11 @@ bool DesktopShellView::DoContextMenu(int x, int y)
HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y)
{ {
IContextMenu* pcm1; IContextMenu* pcm1;
IContextMenu* pcm;
HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm1); HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm1);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
// Get the higher version context menu interfaces. IContextMenu* pcm = _cm_ifs.query_interfaces(pcm1);
_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;
HMENU hmenu = CreatePopupMenu(); 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); UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL);
_pctxmenu2 = NULL; _cm_ifs.reset();
#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
_pctxmenu3 = NULL;
#endif
if (idCmd == FCIDM_SHVIEWLAST-1) { if (idCmd == FCIDM_SHVIEWLAST-1) {
explorer_about(_hwnd); explorer_about(_hwnd);

View file

@ -165,9 +165,9 @@ public:
/// subclassed ShellView window /// subclassed ShellView window
struct DesktopShellView : public SubclassedWindow struct DesktopShellView : public ExtContextMenuHandlerT<SubclassedWindow>
{ {
typedef SubclassedWindow super; typedef ExtContextMenuHandlerT<SubclassedWindow> super;
DesktopShellView(HWND hwnd, IShellView* pShellView); DesktopShellView(HWND hwnd, IShellView* pShellView);
@ -180,16 +180,11 @@ protected:
int Command(int id, int code); int Command(int id, int code);
int Notify(int id, NMHDR* pnmh); 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); HRESULT DoDesktopContextMenu(int x, int y);
void PositionIcons(int dir=1); void PositionIcons(int dir=1);
DesktopDropTarget* _pDropTarget; DesktopDropTarget* _pDropTarget;
HWND _hwndListView; HWND _hwndListView;
int _icon_algo; int _icon_algo;
IContextMenu2* _pctxmenu2;
#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
IContextMenu3* _pctxmenu3;
#endif
}; };

View file

@ -24,4 +24,7 @@
- hide desktop bar when showing full screen applications - hide desktop bar when showing full screen applications
- new start menu entry "Filemanager" close to "Explore" -> display C: and D: drive in MDI window - 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. - 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

View 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(); ShellPath shell_path = create_absolute_pidl();
LPCITEMIDLIST pidl_abs = shell_path; 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); HRESULT hr = (*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast);
if (SUCCEEDED(hr)) { 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(); parentFolder->Release();
} }
@ -442,7 +442,7 @@ HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos)
ShellFolder parent_folder = parent_path; ShellFolder parent_folder = parent_path;
return ShellFolderContextMenu(parent_folder, hwnd, 1, &pidl, pos.x, pos.y); 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);
} }
} }

View file

@ -112,7 +112,7 @@ public:
virtual ShellPath create_absolute_pidl() const {return (LPCITEMIDLIST)NULL;} virtual ShellPath create_absolute_pidl() const {return (LPCITEMIDLIST)NULL;}
virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut);
virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); 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);
}; };

View 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
: ChildWindow(hwnd, info) : super(hwnd, info)
{ {
CONTEXT("FileChildWindow::FileChildWindow()"); CONTEXT("FileChildWindow::FileChildWindow()");
@ -433,7 +433,7 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
if (dis->CtlID == IDW_TREE_LEFT) if (dis->CtlID == IDW_TREE_LEFT)
_left->draw_item(dis, entry); _left->draw_item(dis, entry);
else else if (dis->CtlID == IDW_TREE_RIGHT)
_right->draw_item(dis, entry); _right->draw_item(dis, entry);
return TRUE;} return TRUE;}
@ -507,7 +507,7 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
if (idx != -1) { if (idx != -1) {
Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx); 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;} break;}

View file

@ -85,9 +85,9 @@ struct WebChildWndInfo : public FileChildWndInfo
/// MDI child window displaying file lists /// 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); FileChildWindow(HWND hwnd, const FileChildWndInfo& info);

View file

@ -1564,7 +1564,7 @@ void SDIMainFrame::update_shell_browser()
} }
_shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd, _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
_shellpath_info, _himlSmall, this)); _shellpath_info, _himlSmall, this, _cm_ifs));
_shellBrowser->Init(_hwnd); _shellBrowser->Init(_hwnd);

View file

@ -124,9 +124,13 @@ protected:
#endif #endif
struct SDIMainFrame : public ShellBrowserChildT<MainFrameBase> struct SDIMainFrame : public ExtContextMenuHandlerT<
ShellBrowserChildT<MainFrameBase>
>
{ {
typedef ShellBrowserChildT<MainFrameBase> super; typedef ExtContextMenuHandlerT<
ShellBrowserChildT<MainFrameBase>
> super;
SDIMainFrame(HWND hwnd); SDIMainFrame(HWND hwnd);

View 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 // output type/class name
if (visible_cols & COL_TYPE) { if (visible_cols & COL_TYPE) {
if (calcWidthCol == -1) 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) 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; ++col;
@ -623,9 +623,9 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
// output content / symbolic link target / comment // output content / symbolic link target / comment
if (visible_cols & COL_CONTENT) { if (visible_cols & COL_CONTENT) {
if (calcWidthCol == -1) 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) 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(""));
} }
} }

View file

@ -31,13 +31,15 @@
#include "../explorer_intres.h" #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), : _hwnd(hwnd),
_left_hwnd(left_hwnd), _left_hwnd(left_hwnd),
_right_hwnd(right_hwnd), _right_hwnd(right_hwnd),
_create_info(create_info), _create_info(create_info),
_himl(himl), _himl(himl),
_callback(cb) _callback(cb),
_cm_ifs(cm_ifs)
{ {
_pShellView = NULL; _pShellView = NULL;
_pDropTarget = NULL; _pDropTarget = NULL;
@ -204,7 +206,7 @@ void ShellBrowser::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh)
Entry* entry = (Entry*)itemData; Entry* entry = (Entry*)itemData;
ClientToScreen(_left_hwnd, &tvhti.pt); 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, _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
_shellpath_info, _himlSmall, this)); _shellpath_info, _himlSmall, this, _cm_ifs));
_shellBrowser->Init(_hwndFrame); _shellBrowser->Init(_hwndFrame);
} }

View file

@ -57,7 +57,8 @@ struct BrowserCallback
/// Implementation of IShellBrowserImpl interface in explorer child windows /// Implementation of IShellBrowserImpl interface in explorer child windows
struct ShellBrowser : public IShellBrowserImpl 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(); virtual ~ShellBrowser();
//IOleWindow //IOleWindow
@ -153,6 +154,8 @@ protected:
Root _root; Root _root;
ShellDirectory* _cur_dir; ShellDirectory* _cur_dir;
CtxMenuInterfaces& _cm_ifs;
void InitializeTree(HIMAGELIST himl); void InitializeTree(HIMAGELIST himl);
bool InitDragDrop(); bool InitDragDrop();
@ -231,9 +234,13 @@ protected:
#ifndef _NO_MDI #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); MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info);

View 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); ShellDirectory* dir = static_cast<ShellDirectory*>(_up);
ShellFolder folder = dir? dir->_folder: GetDesktopFolder(); ShellFolder folder = dir? dir->_folder: GetDesktopFolder();
LPCITEMIDLIST pidl = _pidl; 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);
} }

View file

@ -36,7 +36,7 @@ struct ShellEntry : public Entry
virtual ShellPath create_absolute_pidl() const; virtual ShellPath create_absolute_pidl() const;
virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut);
virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); 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; IShellFolder* get_parent_folder() const;

View file

@ -247,7 +247,7 @@ LRESULT QuickLaunchBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
} }
if (entry) // entry is NULL for desktop switch buttons 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 else
goto def; goto def;
break;} break;}

View file

@ -57,9 +57,9 @@ struct QuickLaunchMap : public map<int, QuickLaunchEntry>
/// quick launch bar window /// quick launch bar window
struct QuickLaunchBar : public SubclassedWindow struct QuickLaunchBar : public ExtContextMenuHandlerT<SubclassedWindow>
{ {
typedef SubclassedWindow super; typedef ExtContextMenuHandlerT<SubclassedWindow> super;
QuickLaunchBar(HWND hwnd); QuickLaunchBar(HWND hwnd);
~QuickLaunchBar(); ~QuickLaunchBar();

View file

@ -442,7 +442,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
Entry* entry = *it; Entry* entry = *it;
if (entry) { 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 break; ///@todo handle context menu for more than one entry
} }
} }

View file

@ -202,15 +202,15 @@ extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON
*/ */
struct StartMenu : struct StartMenu :
#ifdef _LIGHT_STARTMENU #ifdef _LIGHT_STARTMENU
public OwnerDrawParent<Window> public ExtContextMenuHandlerT<OwnerDrawParent<Window> >
#else #else
public OwnerDrawParent<DialogWindow> public ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> >
#endif #endif
{ {
#ifdef _LIGHT_STARTMENU #ifdef _LIGHT_STARTMENU
typedef OwnerDrawParent<Window> super; typedef ExtContextMenuHandlerT<OwnerDrawParent<Window> > super;
#else #else
typedef OwnerDrawParent<DialogWindow> super; typedef ExtContextMenuHandlerT<OwnerDrawParent<DialogWindow> > super;
#endif #endif
StartMenu(HWND hwnd); StartMenu(HWND hwnd);

View 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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); #ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
// HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); _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)) { if (SUCCEEDED(hr)) {
IContextMenu* pcm = cm_ifs.query_interfaces(pcm1);
HMENU hmenu = CreatePopupMenu(); HMENU hmenu = CreatePopupMenu();
if (hmenu) { if (hmenu) {
@ -488,6 +539,8 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL); UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL);
cm_ifs.reset();
if (idCmd) { if (idCmd) {
CMINVOKECOMMANDINFO cmi; CMINVOKECOMMANDINFO cmi;

View 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -1003,4 +1003,77 @@ protected:
LPIDA _pIDList; 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);