Is there a way to allow popups within embedded WPF WebBrowser control? I didn't manage to find someone elses solution, nor COM interface which enables allowing popups.
I wouldn't like to change users registry settings or use similar invasive methods, as application is intended to be distributed through ClickOnce.
You can implement custom popups by handling NewWindow2
or NewWindow3
events sourced by the underlying WebBrowser ActiveX control. Below is a very basic example of how to do this. It can be further improved with a re-usable WebBrowser
-based control, to support popups from popups.
Updated to address the comment. To disable the built-in pop-up blocker, you need to implement WebBrowser Feature Control for FEATURE_WEBOC_POPUPMANAGEMENT
. You do need to access Registry.CurrentUser
hive, but that doesn't require admin rights. The code below shows how to do it.
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Microsoft.Win32;
namespace WpfWbApp
{
public partial class MainWindow : Window
{
WebBrowser webBrowser;
public MainWindow()
{
SetBrowserFeatureControl();
InitializeComponent();
this.webBrowser = new WebBrowser();
this.Content = this.webBrowser;
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var axWebBrowser = (SHDocVw.WebBrowser)GetActiveXInstance(this.webBrowser);
axWebBrowser.NewWindow2 += axWebBrowser_NewWindow2;
this.webBrowser.Navigate("http://example.com");
}
void axWebBrowser_NewWindow2(ref object ppDisp, ref bool Cancel)
{
var window = new Window { Width = 400, Height = 300 };
var newWebBrowser = new WebBrowser();
window.Content = newWebBrowser;
window.Show();
ppDisp = GetActiveXInstance(newWebBrowser);
}
/// <summary>
/// Get the underlying WebBrowser ActiveX object;
/// this code depends on SHDocVw.dll COM interop assembly,
/// generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
/// and add as a reference to the project
/// </summary>
static object GetActiveXInstance(WebBrowser browser)
{
var document = browser.Document;
return browser.GetType().InvokeMember("ActiveXInstance",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, browser, new object[] { }) as SHDocVw.WebBrowser;
}
/// <summary>
/// SetBrowserFeatureControlKey
/// </summary>
static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
{
using (var key = Registry.CurrentUser.CreateSubKey(
string.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
RegistryKeyPermissionCheck.ReadWriteSubTree))
{
key.SetValue(appName, (uint)value, RegistryValueKind.DWord);
}
}
/// <summary>
/// SetBrowserFeatureControl
/// </summary>
static void SetBrowserFeatureControl()
{
// http://msdn.microsoft.com/en-us/library/ee330720(v=vs.85).aspx
// FeatureControl settings are per-process
var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
// make the control is not running inside Visual Studio Designer
if (string.Compare(fileName, "devenv.exe", true) == 0 || string.Compare(fileName, "XDesProc.exe", true) == 0)
return;
// Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode.
SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, 10000);
// Web Browser Control Popup Management
SetBrowserFeatureControlKey("FEATURE_WEBOC_POPUPMANAGEMENT", fileName, 0);
}
}
}
According to the docs, the pop-up blocker can also be disabled with CoInternetSetFeatureEnabled
and FEATURE_WEBOC_POPUPMANAGEMENT
, via p/invoke. I haven't tried that venue myself.