当然有办法获得当前文件夹视图的完整视图下拉菜单吗?
动机: 创建我们自己的文件对话框,其外观和功能如下:其行为与 std 通用对话框非常相似
问题:如何获取当前文件夹/shell 容器的视图下拉列表
明显死角:
- < strong>查询 IShellFolder 的 IContextMenu < NULL 接口指针。
- 查询 IShellView 的 IContextMenu < NULL 接口指针。
- IShellFolder::CreateViewObject(IID_IContextMenu...) <非常有限的上下文菜单(新)。
- IShellFolder::GetUIObjectOf(IID_IContextMenu...) <有限的上下文菜单(打开、浏览等)。
- 实现 IShellBrowser 的 InsertMenusSB、RemoveMenusSB 和 SetMenuSB <菜单中的填充内容永远不会超出我填充的内容
我花了一些时间阅读 实现文件夹视图 和 如何托管 IContextMenu。这似乎表明上面的最终方法(实现 InsertMenuSB,...)应该有效。 IShellView 应该使用适当的项目填充 IShellBrowser 的共享菜单,包括其视图子菜单。然而,到目前为止,我从中得到的只是一个空菜单(除非我用项目填充它 - 在这种情况下,我只得到我填充它的项目)。
当然有办法做到这一点。 Windows 资源管理器从某处到达它显示的菜单(如果在 Vista 或更高版本上按下 ALT)。我无法想象这个菜单是由资源管理器本身静态构建的 - 它肯定是以某种方式动态创建的,与当前显示的 IShellView 一致,以允许 shell 扩展显示正确的视图选项列表(和其他菜单选项)。
但有关 InsertMenuSB、RemoveMenuSB 和 SetMenuSB 的文档令人困惑。这似乎表明,作为容器服务器,我应该在元素 0、2 和 4 中填充提供的 OLEMENUGROUPWIDTHS,“以反映它在文件中提供的菜单元素的数量, View 和 Window 菜单组。”
我已经实现了以下内容来尝试正确履行此合同:
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;
}
是否有人实现了类似 Explorer 的项目,可以正确地将当前 IShellView 的菜单公开给最终用户?
是否有关于 IOLEInPlaceFrame 实现的文档/示例可以阐明这个模糊的主题?
呃!@ - 我觉得我一定很接近 - 但还不够接近!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 SVGIO_BACKGROUND 获取文件夹的背景菜单,该菜单应该有一个视图子菜单。 “查看”菜单项的索引、名称和命令 ID 可能因 Windows 版本和本地语言而异,因此这是一种 hack。
use SVGIO_BACKGROUND to get the background menu of the folder, which should have a view submenu. the index, name and the command id of the "view" menu item may vary between windows versions and local languages, so this is kind of hack.
对于那些可能感兴趣的人,这是我正在使用的给定答案的实现:
For those who might be interested, here's the implementation of the given answer I'm using:
您正在重新实现一个众所周知的难以正确使用的控件,而且自开始使用 Windows 以来,许多人都知道并使用过该控件。任何未能使其完全正确的行为都会至少惹恼部分用户,并且“完全正确”的定义将随着 Windows 版本的不同而发生变化。
为什么不能使用默认的呢?您正在实施什么来为该对话框添加如此多的价值以至于标准对话框无法使用?
You are reimplementing a notoriously difficult control to get right, and one that many, many people know and have used since they started using Windows. Any failure to get it exactly right will annoy at least some subset of your users, and the definition of 'exactly right' is going to change from windows release to windows release.
Why can't you use the default one? What are you implementing that adds so much value to this dialog that the standard one is impossible to use?