1

我正在托管一个 Web 浏览器控件,并希望提供我自己的上下文菜单。

理想情况下,我想展示我自己的上下文菜单,其中包含原始浏览器的上下文菜单(包含所有插件等)作为子菜单。

如果这不可能/很难,我可以正常显示我的上下文菜单,并在用户按下 SHIFT 时显示原始菜单。

我需要实现IDocHostUIHandler吗?如果是,如何指定自定义上下文菜单,如何强制使用原始菜单?如何让控件使用我的实现?

控件是这样创建的(省略错误处理):

HRESULT hr=AtlAxCreateControlEx(
   L"Shell.Explorer",m_wndWebCtrl.m_hWnd,
   NULL,NULL,(IUnknown**)&unk,
   IID_IWebBrowser2, NULL); // (IPersistStreamInit*)this);

hr = AtlAdviseSinkMap( this, true);

IUnknownPtr unk;
AtlAxGetControl(m_wndWebCtrl.m_hWnd, &unk);

IWebBrowser2Ptr browser2 = unk;
4

2 回答 2

1

是的,您确实需要实施IDocHostUIHandler.

好的,我想您可以拦截右键单击、击键和其他通常会显示上下文菜单的消息……但这可能迟早会严重损坏;至少,我希望它能够打破可访问性。

拦截IDocHostUIHandler::ShowContextMenu()后,您可以选择在显示自己的菜单后返回S_OK以静默内置菜单。为此,您可以使用普通的 Win32 菜单例程、自定义控件,甚至可以使用精美的 HTML,如果这对您有用的话。根据文档,提供了足够的上下文以允许您确定请求的元素上下文以及默认上下文菜单什么。

不幸的是,我不知道如何处理内置菜单。如果用户选择“原始”选项,您可能会通过显示上下文菜单然后返回来伪造它S_FALSE,但即便如此,也无法将结果菜单附加到现有的弹出菜单(当您返回时确实应该消失无论如何,如果您正在运行此类弹出窗口常见的模态循环)。可以向内置菜单添加选项。

当请求菜单时,您应该能够使用GetKeyboardState()来确定 shift 键的状态。


假设您无论如何都只想要正常浏览器功能的一个子集,那么只需重新实现您想要的选项(后退、前进、打印)并在用户选择它们时调用适当的命令,您可能会得到更好的服务。或者,如果您只想在非常特定的场景中使用普通菜单(例如:在文本区域中编辑命令),请使用ShowContextMenu()参数来识别它,然后才返回S_FALSE以触发默认设置。后一种技术我很幸运。毕竟,它们应该上下文菜单......

于 2009-07-08T17:33:22.297 回答
1

我正在添加以下信息,如何将您自己的 DocHostUI 实现“注入”到浏览器控件中:

默认方式是实现IOleClientSite,并IDocHostUIHandler在实现对象上支持 。

有一种更简单的方法:在DocumentComplete处理程序中,查询IHTMLDocumenntfor ICustomDoc,它允许您从独立对象提供接口。这允许您保留您的环境提供的任何 IOleClientSite 实现。

更多细节可以在这里找到。

于 2009-07-09T11:13:36.507 回答