lean explorer: get and use the parent folder to display correct context menu in all cases 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/shellclass es.h _____
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .cpp --- branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .cpp 2005-12-28 21:46:31 UTC (rev 20405) +++ branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .cpp 2005-12-28 22:45:04 UTC (rev 20406) @@ -197,6 +197,66 @@
} }
+ // local replacement implementation for SHBindToParent() + // (derived from http://www.geocities.com/SiliconValley/2060/articles/shell-helpers.html) +static HRESULT my_SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, VOID** ppv, LPCITEMIDLIST* ppidlLast) +{ + HRESULT hr; + + if (!ppv) + return E_POINTER; + + // There must be at least one item ID. + if (!pidl || !pidl->mkid.cb) + return E_INVALIDARG; + + // Get the desktop folder as root. + ShellFolder desktop; +/* IShellFolderPtr desktop; + hr = SHGetDesktopFolder(&desktop); + if (FAILED(hr)) + return hr; */ + + // Walk to the penultimate item ID. + LPCITEMIDLIST marker = pidl; + for (;;) + { + LPCITEMIDLIST next = reinterpret_cast<LPCITEMIDLIST>( + marker->mkid.abID - sizeof(marker->mkid.cb) + marker->mkid.cb); + if (!next->mkid.cb) + break; + marker = next; + } + + if (marker == pidl) + { + // There was only a single item ID, so bind to the root folder. + hr = desktop->QueryInterface(riid, ppv); + } + else + { + // Copy the ID list, truncating the last item. + int length = marker->mkid.abID - pidl->mkid.abID; + if (LPITEMIDLIST parent_id = reinterpret_cast<LPITEMIDLIST>( + malloc(length + sizeof(pidl->mkid.cb)))) + { + LPBYTE raw_data = reinterpret_cast<LPBYTE>(parent_id); + memcpy(raw_data, pidl, length); + memset(raw_data + length, 0, sizeof(pidl->mkid.cb)); + hr = desktop->BindToObject(parent_id, 0, riid, ppv); + free(parent_id); + } + else + return E_OUTOFMEMORY; + } + + // Return a pointer to the last item ID. + if (ppidlLast) + *ppidlLast = marker; + + return hr; +} + void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPOINT pptScreen) { CONTEXT("ShellBrowserChild::Tree_DoItemMenu()"); @@ -214,10 +274,21 @@ 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; + LPCITEMIDLIST pidl_abs = shell_path;
- ///@todo use parent folder instead of desktop - CHECKERROR(ShellFolderContextMenu(GetDesktopFolder(), _hwnd, 1, &pidl, pptScreen->x, pptScreen->y, _cm_ifs)); + IShellFolder* parentFolder; + LPCITEMIDLIST pidlLast; + + // get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ... + HRESULT hr = my_SHBindToParent(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); + + if (SUCCEEDED(hr)) { + hr = ShellFolderContextMenu(parentFolder, _hwnd, 1, &pidlLast, pptScreen->x, pptScreen->y, _cm_ifs); + + parentFolder->Release(); + } + + CHECKERROR(hr); } } } @@ -289,7 +360,7 @@ ShellDirectory* entry = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, pnmtv->itemNew.hItem);
if (entry) - if (!InsertSubitems(pnmtv->itemNew.hItem, entry, entry->_folder)) { + if (!InsertSubitems(pnmtv->itemNew.hItem, entry)) { entry->_shell_attribs &= ~SFGAO_HASSUBFOLDER;
// remove subitem "+" @@ -304,7 +375,7 @@ } }
-int ShellBrowserChild::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder) +int ShellBrowserChild::InsertSubitems(HTREEITEM hParentItem, Entry* entry) { CONTEXT("ShellBrowserChild::InsertSubitems()");
@@ -347,9 +418,9 @@ tvInsert.hParent = hParentItem;
TreeView_InsertItem(_left_hwnd, &tvInsert); + + ++cnt; } - - ++cnt; }
SendMessage(_left_hwnd, WM_SETREDRAW, TRUE, 0); _____
Modified: branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .h --- branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .h 2005-12-28 21:46:31 UTC (rev 20405) +++ branches/lean-explorer/reactos/subsys/system/explorer/shell/shellbrowser .h 2005-12-28 22:45:04 UTC (rev 20406) @@ -128,7 +128,7 @@
LRESULT Init(HWND hWndFrame); void InitializeTree(); - int InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder); + int InsertSubitems(HTREEITEM hParentItem, Entry* entry); bool InitDragDrop();
HRESULT OnDefaultCommand(LPIDA pida); @@ -148,9 +148,9 @@ int _last_split; RECT _clnt_rect;
- /*virtual*/ void resize_children(); - /*virtual*/ void jump_to(LPCTSTR path); - /*virtual*/ void jump_to(LPCITEMIDLIST pidl); + void resize_children(); + void jump_to(LPCTSTR path); + void jump_to(LPCITEMIDLIST pidl);
void jump_to(Entry* entry);
_____
Modified: branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclass es.h --- branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclass es.h 2005-12-28 21:46:31 UTC (rev 20405) +++ branches/lean-explorer/reactos/subsys/system/explorer/utility/shellclass es.h 2005-12-28 22:45:04 UTC (rev 20406) @@ -1079,5 +1079,6 @@
CtxMenuInterfaces _cm_ifs; };
+ extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl,
LPCITEMIDLIST* ppidl, int x, int y, CtxMenuInterfaces& cm_ifs);