如何在我创build的另一个窗口中显示来自WebBrowser的popup窗口?
我正试图在我的一个应用程序中实现一个简单的Web浏览器控件。 这是为了帮助将Web应用程序集成到我正在创build的工具集中。
问题是,这个网页应用程序绝对喜欢popup窗口….
当一个popup窗口被打开时,它会在一个IE窗口中打开,这个窗口不是我的主窗口所属的MDI容器窗体的子窗口。
我怎样才能得到任何和所有popup窗口创build通过点击我的WebBrowser中的链接是我的MDI容器的子项(类似于设置窗体的MDIParent属性)?
提前致谢。
Web浏览器控件支持NewWindow事件以获得有关popup窗口的通知。 Winforms包装但是不能让你做太多,你只能取消popup。 原生的COM包装允许传回一个新的Web浏览器实例,那个实例将被用来显示popup窗口。
利用这个需要一些工作。 对于初学者,使用项目+添加引用,浏览选项卡,并selectc:\ windows \ system32 \ shdocvw.dll。 这增加了对本地COM接口的引用。
创build一个充当popup窗体的窗体。 放下一个WebBrowser,并使其代码如下所示:
public partial class Form2 : Form { public Form2() { InitializeComponent(); } public WebBrowser Browser { get { return webBrowser1; } } }
浏览器属性允许访问将用于在popup窗口中显示网页的浏览器。
现在回到主窗体。 放下一个WebBrowser,并使其代码如下所示:
public partial class Form1 : Form { public Form1() { InitializeComponent(); webBrowser1.Url = new Uri("http://google.com"); } SHDocVw.WebBrowser nativeBrowser; protected override void OnLoad(EventArgs e) { base.OnLoad(e); nativeBrowser = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance; nativeBrowser.NewWindow2 += nativeBrowser_NewWindow2; } protected override void OnFormClosing(FormClosingEventArgs e) { nativeBrowser.NewWindow2 -= nativeBrowser_NewWindow2; base.OnFormClosing(e); } void nativeBrowser_NewWindow2(ref object ppDisp, ref bool Cancel) { var popup = new Form2(); popup.Show(this); ppDisp = popup.Browser.ActiveXInstance; } }
OnLoad方法获得对本机COM接口的引用,然后订阅NewWindow2事件的事件处理程序。 我确保在FormClosing事件处理程序中取消订阅该事件,而不是100%确定是否有必要。 更安全,然后抱歉。
NewWindow2事件处理程序是关键,注意第一个参数允许传回一个无types的引用。 这应该是popup窗口中的本地浏览器。 所以我创build了一个Form2和Show()它的实例。 注意Show()的参数,确保popup窗口是一个拥有的窗口。 根据需要replace为你的应用程序,我假设你想在你的情况下创build一个MDI子窗口。
请注意,当Javascript使用alert()时,此事件不会触发显示的窗口。 浏览器不会将该窗口视为HTMLpopup窗口,也不会使用浏览器窗口进行显示,因此无法截取或replace它。
我发现最好的办法是实现/下沉NewWindow3事件
添加对c:\ windows \ system32 \ shdocvw.dll的引用,如其他答案中所述。
添加事件处理程序
SHDocVw.WebBrowser wbCOMmain = (SHDocVw.WebBrowser)webbrowser.ActiveXInstance; wbCOMmain.NewWindow3 += wbCOMmain_NewWindow3;
事件方法
void wbCOMmain_NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl) { // bstrUrl is the url being navigated to Cancel = true; // stop the navigation // Do whatever else you want to do with that URL // open in the same browser or new browser, etc. }
- 将“Interop.SHDocVw”程序集的“embeddedInteroptypes”设置为false
- 将“本地副本”设置为true。
来源为帮助MSDN Post
精炼汉斯答案,你可以派生WebBrowser访问COM而不添加引用。 它是通过使用未发布的Winforms WebBrowser.AttachInterface和DetachInterface方法。
这里更详细的阐述。
这里是代码:
用法(将您的WebBrowser实例更改为WebBrowserNewWindow2)
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.webBrowser1.NewWindow2 += webBrowser_NewWindow2; } protected override void OnFormClosing(FormClosingEventArgs e) { webBrowser1.NewWindow2 -= webBrowser_NewWindow2; base.OnFormClosing(e); } void webBrowser_NewWindow2(object sender, WebBrowserNewWindow2EventArgs e) { var popup = new Form1(); popup.Show(this); e.PpDisp = popup.Browser.ActiveXInstance; } public WebBrowserNewWindow2 Browser { get { return webBrowser1; } } }
码:
using System; using System.Security.Permissions; using System.Runtime.InteropServices; using System.Windows.Forms; namespace SHDocVw { public delegate void WebBrowserNewWindow2EventHandler(object sender, WebBrowserNewWindow2EventArgs e); public class WebBrowserNewWindow2EventArgs : EventArgs { public WebBrowserNewWindow2EventArgs(object ppDisp, bool cancel) { PpDisp = ppDisp; Cancel = cancel; } public object PpDisp { get; set; } public bool Cancel { get; set; } } public class WebBrowserNewWindow2 : WebBrowser { private AxHost.ConnectionPointCookie _cookie; private WebBrowser2EventHelper _helper; [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void CreateSink() { base.CreateSink(); _helper = new WebBrowser2EventHelper(this); _cookie = new AxHost.ConnectionPointCookie( this.ActiveXInstance, _helper, typeof(DWebBrowserEvents2)); } [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void DetachSink() { if (_cookie != null) { _cookie.Disconnect(); _cookie = null; } base.DetachSink(); } public event WebBrowserNewWindow2EventHandler NewWindow2; private class WebBrowser2EventHelper : StandardOleMarshalObject, DWebBrowserEvents2 { private readonly WebBrowserNewWindow2 _parent; public WebBrowser2EventHelper(WebBrowserNewWindow2 parent) { _parent = parent; } public void NewWindow2(ref object pDisp, ref bool cancel) { WebBrowserNewWindow2EventArgs arg = new WebBrowserNewWindow2EventArgs(pDisp, cancel); _parent.NewWindow2(this, arg); if (pDisp != arg.PpDisp) pDisp = arg.PpDisp; if (cancel != arg.Cancel) cancel = arg.Cancel; } } [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), TypeLibType(TypeLibTypeFlags.FHidden)] public interface DWebBrowserEvents2 { [DispId(0xfb)] void NewWindow2( [In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp, [In, Out] ref bool cancel); } } }