【问题标题】:How do I display a popup from a WebBrowser in another window I created?如何在我创建的另一个窗口中显示来自 WebBrowser 的弹出窗口?
【发布时间】:2011-06-24 16:28:45
【问题描述】:

我正在尝试在我的一个应用中实现一个简单的 Web 浏览器控件。这是为了帮助将 Web 应用程序集成到我正在创建的工具集中。

问题是,这个网络应用绝对喜欢弹出窗口......

当打开一个弹出窗口时,它会在一个 IE 窗口中打开,该窗口不是我的主窗口所在的 MDI 容器窗体的子窗体。

如何让通过单击 WebBrowser 中的链接创建的所有弹出窗口成为 MDI 容器的子项(类似于设置表单的 MDIParent 属性)?

提前致谢。

【问题讨论】:

  • 弹出窗口是什么意思? window.open?window.createpopup?

标签: c# webbrowser-control mdiparent


【解决方案1】:

Web 浏览器控件支持 NewWindow 事件以获取有关弹出窗口的通知。然而,Winforms 包装器并不能让你做太多事情,你只能取消弹出窗口。本机 COM 包装器允许传回 Web 浏览器的新实例,然后该实例将用于显示弹出窗口。

利用这一点需要做一些工作。对于初学者,使用 Project + Add Reference,Browse 选项卡并选择 c:\windows\system32\shdocvw.dll。这添加了对本机 COM 接口的引用。

创建一个充当弹出表单的表单。在其上放置一个 WebBrowser 并使其代码看起来像这样:

public partial class Form2 : Form {
    public Form2() {
        InitializeComponent();
    }
    public WebBrowser Browser {
        get { return webBrowser1; }
    }
}

Browser 属性允许访问将用于在弹出窗口中显示网页的浏览器。

现在回到主窗体。在其上放置一个 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 事件处理程序是关键,注意第一个参数允许传回一个无类型的引用。那应该是弹出窗口中的本机浏览器。所以我创建了一个 Form2 的实例并 Show() 它。注意 Show() 的参数,它确保弹出窗口是一个拥有的窗口。根据您的应用程序的需要替换它,我假设您希望在您的情况下创建一个 MDI 子窗口。

请注意,当 Javascript 使用 alert() 时显示的窗口不会触发此事件。浏览器不会将该窗口视为 HTML 弹出窗口,也不会使用浏览器窗口来显示它,因此您无法拦截或替换它。

【讨论】:

  • 这个解决方案已经没用了!
  • @rima - 在带有 IE10 和 VS2012 的 Windows 8 上重新测试。仍然工作得很好。点击按钮而不是投票按钮。
  • 您还可以从“添加参考”屏幕安装 com 组件。选择 COM 并选择 Microsoft Internet Controls
  • @rima 而不是仅仅说它不起作用。请提供你的理由。
  • 一个奇怪的问题——为什么 activeX 实例在表单构造函数中为 null 而在 onLoad 中不为 null 背后是否有一些值得了解的背景?
【解决方案2】:

我发现最好的方法是实现/接收NewWindow3 event

添加对 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”程序集的“嵌入互操作类型”设置为 false
  • 将“本地副本”设置为 true。

该帮助的来源MSDN Post

【讨论】:

    【解决方案3】:

    提炼汉斯的答案,您可以在不添加引用的情况下派生用于访问 COM 的 WebBrowser。它是通过使用未发布的 Winforms WebBrowser.AttachInterface 和 DetachInterface 方法。

    更详细的here

    代码如下:

    用法(将您的 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);
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      我知道这个问题很老了,但我用这种方法解决了:添加新引用,在 COM 中选择 Microsoft Internet Controls 并在代码中,在单击打开新窗口之前添加以下内容:

      SHDocVw.WebBrowser_V1 axBrowser = (SHDocVw.WebBrowser_V1)webBrowser1.ActiveXInstance;
      axBrowser.NewWindow += axBrowser_NewWindow;
      

      然后添加如下方法:

      void axBrowser_NewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
      {
          Processed = true;
          webBrowser1.Navigate(URL);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多