owner drawn context menus for lean explorer version
Modified: branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.cpp
Modified: branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.h
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.cpp
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.h
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.cpp
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.h
Modified: branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.cpp
Modified: branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.h
Modified: trunk/reactos/subsys/system/explorer/desktop/desktop.cpp
Modified: trunk/reactos/subsys/system/explorer/utility/shellclasses.cpp

Modified: branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.cpp
--- branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -439,11 +439,11 @@
 	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 @@
 	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 @@
 	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 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 @@
 
 				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) {

Modified: branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.h
--- branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.h	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/desktop/desktop.h	2005-02-06 14:03:25 UTC (rev 13440)
@@ -163,9 +163,9 @@
 
 
  /// subclassed ShellView window
-struct DesktopShellView : public SubclassedWindow
+struct DesktopShellView : public ExtContextMenuHandlerT<SubclassedWindow>
 {
-	typedef SubclassedWindow super;
+	typedef ExtContextMenuHandlerT<SubclassedWindow> super;
 
 	DesktopShellView(HWND hwnd, IShellView* pShellView);
 
@@ -178,7 +178,7 @@
 	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;

Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.cpp
--- branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -103,7 +103,7 @@
 		}
 	}
 
-	_shellBrowser = auto_ptr<ShellBrowserChild>(new ShellBrowserChild(_hwnd, _left_hwnd, _right_hwnd, _create_info));
+	_shellBrowser = auto_ptr<ShellBrowserChild>(new ShellBrowserChild(_hwnd, _left_hwnd, _right_hwnd, _create_info, _cm_ifs));
 
 	 // update _shellBrowser->_clnt_rect
 	ClientRect rect(_hwnd);

Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.h
--- branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.h	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/shell/mainframe.h	2005-02-06 14:03:25 UTC (rev 13440)
@@ -31,9 +31,9 @@
 
 
  /// Explorer frame window
-struct MainFrame : public PreTranslateWindow
+struct MainFrame : public ExtContextMenuHandlerT<PreTranslateWindow>
 {
-	typedef PreTranslateWindow super;
+	typedef ExtContextMenuHandlerT<PreTranslateWindow> super;
 
 	MainFrame(HWND hwnd);
 	~MainFrame();

Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.cpp
--- branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -45,11 +45,13 @@
 }
 
 
-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 @@
 			ShellFolder folder = dir? dir->_folder: GetDesktopFolder();
 			LPCITEMIDLIST pidl = static_cast<ShellEntry*>(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 @@
 
 	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;

Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.h
--- branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.h	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser.h	2005-02-06 14:03:25 UTC (rev 13440)
@@ -44,7 +44,8 @@
  /// 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 @@
 
 protected:
 	ShellDirectory*	_cur_dir;
+	CtxMenuInterfaces& _cm_ifs;
 };

Modified: branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.cpp
--- branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -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,14 +468,65 @@
 }
 
 
-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;
 
 	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);
 
 	if (SUCCEEDED(hr)) {
+		pcm = cm_ifs.query_interfaces(pcm);
+
 		HMENU hmenu = CreatePopupMenu();
 
 		if (hmenu) {
@@ -484,6 +535,8 @@
 			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;
 

Modified: branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.h
--- branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.h	2005-02-06 13:28:34 UTC (rev 13439)
+++ branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclasses.h	2005-02-06 14:03:25 UTC (rev 13440)
@@ -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 @@
 	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);

Modified: trunk/reactos/subsys/system/explorer/desktop/desktop.cpp
--- trunk/reactos/subsys/system/explorer/desktop/desktop.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ trunk/reactos/subsys/system/explorer/desktop/desktop.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -522,7 +522,7 @@
 	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:
@@ -599,12 +599,12 @@
 
 HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y)
 {
-	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*)&pcm);
 
 	if (SUCCEEDED(hr)) {
-		IContextMenu* pcm = _cm_ifs.query_interfaces(pcm1);
+		pcm = _cm_ifs.query_interfaces(pcm);
 
 		HMENU hmenu = CreatePopupMenu();
 

Modified: trunk/reactos/subsys/system/explorer/utility/shellclasses.cpp
--- trunk/reactos/subsys/system/explorer/utility/shellclasses.cpp	2005-02-06 13:28:34 UTC (rev 13439)
+++ trunk/reactos/subsys/system/explorer/utility/shellclasses.cpp	2005-02-06 14:03:25 UTC (rev 13440)
@@ -523,13 +523,13 @@
 HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl,
 								LPCITEMIDLIST* apidl, int x, int y, CtxMenuInterfaces& cm_ifs)
 {
-	IContextMenu* pcm1;
+	IContextMenu* pcm;
 
-	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);
+	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);
 
 	if (SUCCEEDED(hr)) {
-		IContextMenu* pcm = cm_ifs.query_interfaces(pcm1);
+		pcm = cm_ifs.query_interfaces(pcm);
 
 		HMENU hmenu = CreatePopupMenu();