Motivation: Creating our own file dialog that looks & acts much like the std common dialog
Problem: How to obtain the view pull-down for the current folder/shell container
Apparent Dead Ends:
- Query the IShellFolder for its IContextMenu < NULL interface pointer.
- Query the IShellView for its IContextMenu < NULL interface pointer.
- IShellFolder::CreateViewObject(IID_IContextMenu...) < very limited context menu (new).
- IShellFolder::GetUIObjectOf(IID_IContextMenu...) < limited context menu (open, explore,...).
- Implement IShellBrowser's InsertMenusSB, RemoveMenusSB, and SetMenuSB < The menu is never populated beyond what I populate it with
I have spent some time reading Implementing a Folder View and How to host an IContextMenu. This seems to indicate that the final approach above (implementing InsertMenuSB, ...) should work. The IShellView should be populating the shared menu for the IShellBrowser, including its View submenu, with the appropriate items. However, so far all I get from that is an empty menu (unless I populate it with items - in which case, I just get the items I populate it with).
Surely there is a way to do this. Windows Explorer arrives at the menu it displays (if you press down ALT on Vista or above) from somewhere. And I cannot imagine that this menu is statically built by Explorer itself - it surely is dynamically created somehow in concert with the currently displayed IShellView to allow for shell extensions to display the correct list of view options (and other menu options).
But the documentation on InsertMenuSB, RemoveMenuSB, and SetMenuSB is confusing. It seems to indicate that, as the container server, I should populate the supplied OLEMENUGROUPWIDTHS, "in elements 0, 2, and 4 to reflect the number of menu elements it provided in the File, View, and Window menu groups."
I have implemented the following to attempt to properly fulfill this contract:
HRESULT STDMETHODCALLTYPE ShellBrowserDlgImpl::InsertMenusSB(__RPC__in HMENU hmenuShared, /* [out][in] */ __RPC__inout LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
TRACE("IShellBrowser::InsertMenusSB\n");
// insert our main pull-downs
struct
{
UINT id;
LPCTSTR label;
} pull_downs[] = {
{ FCIDM_MENU_FILE, "File" },
{ FCIDM_MENU_EDIT, "Edit" },
{ FCIDM_MENU_VIEW, "View" },
{ FCIDM_MENU_TOOLS, "Tools" },
{ FCIDM_MENU_HELP, "Help" },
};
for (size_t i = 0; i < countof(pull_downs); ++i)
{
VERIFY(AppendMenu(hmenuShared, MF_POPUP, pull_downs[i].id, pull_downs[i].label));
ASSERT(GetMenuItemID(hmenuShared, i) == pull_downs[i].id);
}
// set the count of menu items we've inserted into each *group*
lpMenuWidths->width[0] = 2; // FILE: File, Edit
lpMenuWidths->width[2] = 2; // VIEW: View, Tools
lpMenuWidths->width[4] = 1; // WINDOW: Help
return S_OK;
}
Has anyone implemented an Explorer like project that properly exposes the current IShellView's menus to the end-user?
Is there documentation / examples on IOLEInPlaceFrame implementations that might shed some light on this murky subject?
Ugh!@ - I feel like I must be close - yet not close enough!