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">
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