If I host a WebBrowser
in my application, and a javascript code in the web page shown on my WebBrowser calls window.close()
and I click \"Yes\" on
There is an interface DWebBrowserEvents2 which has a method WindowClosing which you can use to cancel the window.close()
call.
(I found the suggestion in this posting)
Which version of the WebBrowser control are you using? The WinForms one or the WPF one?
For the WinForms control, you can try to handle the Disposed or the HandleDestroyed event of the WebBrowser control in order to close your parent form too. For the WPF control, you can try the same with the Unloaded event.
I don't know if other JS code can lead to the same problems.
The best solution in WPF i have found is to use DispatcherTimer:
private readonly DispatcherTimer _dispatcherTimer;
public MyClass()
{
InitializeComponent();
WBrowser.Navigate(loginUri);
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += dispatcherTimer_Tick;
_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
_dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
if (WBrowser.Source == null)
{
_dispatcherTimer.Stop();
Close();
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (_dispatcherTimer.IsEnabled)
{
_dispatcherTimer.Stop();
}
}
private void WBrowser_OnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
if(!_dispatcherTimer.IsEnabled)
{
_dispatcherTimer.Start();
}
}
In WPF you can catch WM_CLOSE message by attaching to WebBrowser's message loop.
public MainWindow()
{
InitializeComponent();
webBrowser.MessageHook += webBrowser_MessageHook;
}
IntPtr webBrowser_MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch(msg)
{
case 0x0010: // WM_CLOSE
handled = true; // cancel event here
// do additional stuff here
break;
}
return IntPtr.Zero;
}
The WebBrowser control doesn't come with a built in method to detect JavaScript.Close event. You can inject your own JS to help you handle this OR you can extend the WebBrowser control to create an event when window.close() is fired.
From this page, I got the following information http://blogs.msdn.com/b/jpsanders/archive/2007/05/25/how-to-close-the-form-hosting-the-webbrowser-control-when-scripting-calls-window-close-in-the-net-framework-version-2-0.aspx
Create a new class file and put the following code in
Public Class MyExtendedBrowserControl
' Based on WebBrowser
Inherits System.Windows.Forms.WebBrowser
' Define constants from winuser.h
Private Const WM_PARENTNOTIFY As Integer = &H210
Private Const WM_DESTROY As Integer = 2
'Define New event to fire
Public Event WBWantsToClose()
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case WM_PARENTNOTIFY
If (Not DesignMode) Then
If (m.WParam = WM_DESTROY) Then
' Tell whoever cares we are closing
RaiseEvent WBWantsToClose()
End If
End If
DefWndProc(m)
Case Else
MyBase.WndProc(m)
End Select
End Sub
End Class
Now, you have to replace the built in WebControl evocation with this new one. Edit the form1.designer.vb file or whatever your form is called. To do this, click "Show All Files" icon in solution explorer to see the designer file. Once you have the designer file opened, replace System.Windows.Forms.WebBrowser with MyExtendedBrowserControl.
Build the project. You'll need to do this for the control to be compiled and have it show up without errors on the form itself.
Now that you built the project, you'll be able to edit the control and access the new WBWantsToClose event. Open the form, click the WebBrowser control, open its properties (F4), click the "events" icon (lightening bolt), double click "WBWantsToClose". That'll take you into the code with the event ready to be handled.