Search code examples
browserwebbrowser-controlvb.net-2010popupwindowaxwebbrowser

Web Browser to handle pop ups within the application


I am trying to use the WebBrowser control to launch a new form for popups instead of it opening in IE. I have tried to use the AxWebBrowser instead to get the popups which works with NewWindow3 event and just doing e.ppDisp = AxWebBrowser.Application, but there are many limitations that come with AxWebBrowser. So instead I am trying to Extend the normal WebBrowser to include the NewWindow3 event like the AxWebBrowser but running into problems. With e.ppDisp = AxWebBrowser.Application I am getting errors: "InvalidVariant was detected" followed by "Specified OLE variant is invalid" if I continue.

Note: This is my first time extending a class so I could be over looking something simple. If I try just navigating to the new URL in the new window, I get java script errors from the site.

I have updated the code base on comments. Have removed the ExtendedWebBrowser class for a munch smaller and nicer version. Here is the New Code:

From the main form and a very similar BrowserPopup form -

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)
    nativeBrowser = DirectCast(ExtendedWebBrowser1.ActiveXInstance, SHDocVw.WebBrowser)
    AddHandler nativeBrowser.NewWindow3, AddressOf nativeBrowser_NewWindow3
    AddHandler nativeBrowser.WindowClosing, AddressOf nativeBrowser_WindowClosing
End Sub

Private Sub nativeBrowser_NewWindow3(ByRef ppDisp As Object, ByRef Cancel As Boolean, ByVal dwflags As UInteger, ByVal bStrUrlContext As String, ByVal bstrUrl As String)
    Dim popup = New BrowserPopup()
    popup.Show(Me)
    popup.browserPop.DocumentText = bStrUrlContext
    ppDisp = popup.browserPop.ActiveXInstance
End Sub

Private Sub nativeBrowser_WindowClosing(ByVal IsChildWindow As Boolean, ByRef Cancel As Boolean)
    MsgBox("working?") '<<<Doesn't Trigger>>>
End Sub

Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
    MyBase.OnFormClosing(e)
End Sub

Also, if it helps, here is the scripting from the page that should be able to close the popup form but just seems to deactivate the WebBrowser instead.

<table isListBtn="false" cellpadding="0" enabled="true" class="buttonBorderBlue"
cellspacing="0" border="0" onClick="if (typeof(workpaneMediator_toolbar)!='undefined')
workpaneMediator_toolbar.onSelect('CANCEL_ACTION', this)"
actionType="CLOSE_WINDOW_TYPE" id="workpaneMediator_toolbar_CANCEL_ACTIONWrapper"
nowrap><tr><td class="buttonBlueTD">

Solution

  • You're right that WindowClosing doesn't get fired for Winforms WebBrowser Control, I confirm that. It appears to be a long-time bug in .NET WebBrowser ActiveX hosting code, which has never been addressed. Check this post for more details and a possible workaround.

    Another possible workaround may be to host WebBrowser ActiveX Control directly via AxHost class, in which case WindowClosing gets fire correctly. Example:

    C#:

    using Microsoft.Win32;
    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WebBrowserApp
    {
        // MainForm
    
        public partial class MainForm : Form 
        {
            WebBrowser webBrowser;
    
            public MainForm()
            {
                InitializeComponent();
                InitBrowser();
    
                if (this.webBrowser.Document == null && this.webBrowser.ActiveXInstance == null)
                    throw new ApplicationException ("Unable to initialize WebBrowser ActiveX control.");
    
                var ax = (SHDocVw.WebBrowser)this.webBrowser.ActiveXInstance;
                ax.NewWindow2 += (ref object ppDisp, ref bool Cancel) =>
                {
                    var popup = new RawBrowserPopup();
                    popup.Visible = true;
                    ppDisp = popup.WebBrowser.ActiveXInstance;
                };
    
                this.Load += (s, e) =>
                {
                    this.webBrowser.DocumentText = "<a target=\"_blank\" href=\"javascript:'<button onclick=\\'window.close()\\'>Close</button>'\">Go</a>";
                };
            }
    
            // create a WebBrowser instance
            void InitBrowser()
            {
                this.webBrowser = new WebBrowser();
                this.webBrowser.Dock = DockStyle.Fill;
                this.Controls.Add(this.webBrowser);
                this.webBrowser.Visible = true;
            }
        }
    
        // RawWebBrowser
    
        public class RawWebBrowser : AxHost
        {
            public RawWebBrowser()
                : base("8856f961-340a-11d0-a96b-00c04fd705a2")
            {
            }
    
            public event EventHandler Initialized;
    
            protected override void AttachInterfaces()
            {
                if (this.Initialized != null)
                    this.Initialized(this, new EventArgs());
            }
    
            public object ActiveXInstance
            {
                get
                {
                    return base.GetOcx();
                }
            }
        }
    
        // RawBrowserPopup
    
        public class RawBrowserPopup : Form
        {
            RawWebBrowser webBrowser;
    
            public RawWebBrowser WebBrowser
            {
                get { return this.webBrowser; }
            }
    
            public RawBrowserPopup()
            {
                this.webBrowser = new RawWebBrowser();
    
                this.webBrowser.Initialized += (s, e) =>
                {
                    var ax = (SHDocVw.WebBrowser)this.webBrowser.ActiveXInstance;
                    ax.NewWindow2 += (ref object ppDisp, ref bool Cancel) =>
                    {
                        var popup = new RawBrowserPopup();
                        popup.Visible = true;
                        ppDisp = popup.WebBrowser.ActiveXInstance;
                    };
    
                    ax.WindowClosing += (bool IsChildWindow, ref bool Cancel) =>
                    {
                        Cancel = true;
                        this.Close();
                    };
                };
    
                this.webBrowser.Dock = DockStyle.Fill;
                this.Controls.Add(this.webBrowser);
                this.webBrowser.Visible = true;
            }
        }
    }
    

    VB.NET:

    Public Class Form1
        Dim webBrowser As WebBrowser = New WebBrowser()
    
        Sub New()
            MyBase.New()
            Me.InitializeComponent()
            webBrowser.Dock = DockStyle.Fill
            Me.Controls.Add(webBrowser)
            webBrowser.Visible = True
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.webBrowser.DocumentText = "<a target='_blank' href='javascript:""<button onclick=\""window.close()\"">Close</button>""'>Go</a>"
    
            Dim ActiveX As SHDocVw.WebBrowser = Me.webBrowser.ActiveXInstance
            AddHandler ActiveX.NewWindow2, AddressOf WebBrowser_ActiveX_NewWindow2
        End Sub
    
        Private Sub WebBrowser_ActiveX_NewWindow2(ByRef ppDisp As Object, ByRef Cancel As Boolean)
            Dim popup As RawBrowserPopup = New RawBrowserPopup()
            popup.Visible = True
            ppDisp = popup.WebBrowser.ActiveXInstance
        End Sub
    End Class
    
    Public Class RawWebBrowser
        Inherits System.Windows.Forms.AxHost
    
        Sub New()
            MyBase.New("8856f961-340a-11d0-a96b-00c04fd705a2")
        End Sub
    
        Event Initialized(sender As Object, e As EventArgs)
    
        Protected Overrides Sub AttachInterfaces()
            RaiseEvent Initialized(Me, New EventArgs())
        End Sub
    
        Public ReadOnly Property ActiveXInstance() As Object
            Get
                Return MyBase.GetOcx()
            End Get
        End Property
    End Class
    
    Public Class RawBrowserPopup
        Inherits System.Windows.Forms.Form
    
        Dim WithEvents rawBrowser As RawWebBrowser = New RawWebBrowser()
    
        Sub New()
            MyBase.New()
            rawBrowser.Dock = DockStyle.Fill
            Me.Controls.Add(rawBrowser)
            rawBrowser.Visible = True
        End Sub
    
        Public ReadOnly Property WebBrowser() As Object
            Get
                Return rawBrowser
            End Get
        End Property
    
        Private Sub rawBrowser_Initialized(sender As Object, e As EventArgs) Handles rawBrowser.Initialized
            Dim activeX As SHDocVw.WebBrowser = rawBrowser.ActiveXInstance
            AddHandler activeX.NewWindow2, AddressOf activeX_NewWindow2
            AddHandler activeX.WindowClosing, AddressOf activeX_WindowClosing
        End Sub
    
        Private Sub activeX_NewWindow2(ByRef ppDisp As Object, ByRef Cancel As Boolean)
            Dim popup As RawBrowserPopup = New RawBrowserPopup()
            popup.Visible = True
            ppDisp = popup.WebBrowser.ActiveXInstance
        End Sub
    
        Private Sub activeX_WindowClosing(IsChildWindow As Boolean, ByRef Cancel As Boolean)
            Cancel = True
            Me.Close()
        End Sub
    
    End Class