我正在托管网络浏览器控件,并希望提供我自己的上下文菜单。
理想情况下,我想提供我自己的上下文菜单,其中包含原始浏览器的上下文菜单(包含所有插件等)作为子菜单。
如果那不可能/狡猾,我会好的,例如通常显示我的上下文菜单,并在用户按下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;
答案 0 :(得分:1)
是的,您需要实施IDocHostUIHandler
。
好吧,我猜你可以拦截右击,击键和其他通常会显示上下文菜单的消息......但是这可能迟早会破坏;至少,我希望它能打破可访问性。
截取IDocHostUIHandler::ShowContextMenu()
后,您可以选择在显示自己的内容后返回S_OK
来压制内置菜单。您可以使用常规的Win32菜单例程,一个自定义控件,甚至是花哨的HTML,如果它适合您。根据文档,提供了足够的上下文,以允许您确定请求的元素上下文,以及将的默认上下文菜单。
不幸的是,我知道无法获得内置菜单的句柄。如果用户选择了“原始”选项,您可以通过显示上下文菜单然后返回S_FALSE
来伪造它,但即使这样,也无法将结果菜单附加到现有的弹出菜单(实际上应该已经消失了)如果你正在运行这种弹出窗口常见的模态循环,那么当你返回的时候)。可以add options to the built-in menus。
在请求菜单时,您应该可以使用GetKeyboardState()
来确定shift键的状态。
假设您只想要正常浏览器功能的子集,只需重新实现所需的选项(后退,前进,打印)并调用相应的命令即可获得更好的服务。用户选择它们。或者,如果您只想在非常特定的场景中使用普通菜单(例如:在textarea中编辑命令),请使用ShowContextMenu()
参数来识别它,然后返回S_FALSE
以触发默认值。我对后一种技术运气不错;毕竟,他们 应该是上下文菜单......
答案 1 :(得分:1)
我正在添加以下信息,如何将您自己的DocHostUI实现“注入”到浏览器控件中:
默认方式是实现IOleClientSite
,并支持实现对象上的IDocHostUIHandler
。
有一种更简单的方法:在DocumentComplete
处理程序中,查询ICustomDoc
的IHTMLDocumennt
,它允许您从独立对象提供接口。这允许您保留环境提供的任何IOleClientSite实现。
可以找到更多详细信息here。