owner drawn context menus for lean explorer version

svn path=/branches/lean-explorer/; revision=13440
This commit is contained in:
Martin Fuchs
2005-02-06 14:03:25 +00:00
parent 49f4d8010f
commit ddef57fcd4
8 changed files with 155 additions and 19 deletions
@@ -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) {
@@ -163,9 +163,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);
@@ -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;
@@ -103,7 +103,7 @@ void MainFrame::update_explorer_view()
}
}
_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);
@@ -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<PreTranslateWindow>
{
typedef PreTranslateWindow super;
typedef ExtContextMenuHandlerT<PreTranslateWindow> super;
MainFrame(HWND hwnd);
~MainFrame();
@@ -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<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 @@ 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;
@@ -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;
};
@@ -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;
@@ -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<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);