Web浏览器和javascript window.close()

如果我在我的应用程序中托管WebBrowser ,并且我的WebBrowser上显示的网页中的javascript代码调用window.close()并在提示符上单击“是”,我的WebBrowser消失,但我的表单保持打开状态。

我不想禁用javascript,而不是按“是”显然不是解决方案。 处理这个问题的最佳方法是什么? 即使用户按下“是”,这是否可以以编程方式取消? 还有,还有像window.close()这样的其他javascript技巧可能会搞砸我应该知道的应用程序吗? (我的应用程序使用WebBrowser搜索Web,因此应考虑每个可能的JavaScript代码。)

有一个接口DWebBrowserEvents2 ,它有一个方法WindowClosing ,您可以使用它来取消window.close()调用。

(我在这篇post中找到了建议)

在WPF中,您可以通过附加到WebBrowser的消息循环来捕获WM_CLOSE消息。

 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; } 

您使用的是哪个版本的WebBrowser控件? WinForms一个还是WPF一个?

对于WinForms控件,您可以尝试处理WebBrowser控件的Disposed或HandleDestroyed事件,以便关闭您的父窗体。 对于WPF控件,您可以尝试使用Unloaded事件。

我不知道其他JS代码是否会导致同样的问题。

我发现WPF中最好的解决方案是使用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(); } } 

WebBrowser控件没有内置方法来检测JavaScript.Close事件。 您可以注入自己的JS来帮助您处理此问题,或者可以在触发window.close()时扩展WebBrowser控件以创建事件。

从这个页面,我得到了以下信息http://blogs.msdn.com/b/jpsanders/archive/2007/05/25/how-to-close-the-form-hosting-the-webbrowser-control-when -scripting通话窗口关闭,在最网框架版本,2-0.aspx

创建一个新的类文件并将以下代码放入

 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 

现在,您必须使用这个新的WebControl evocation替换内置的WebControl。 编辑form1.designer.vb文件或调用任何表单。 为此,请单击解决方案资源管理器中的“显示所有文件”图标以查看设计器文件。 打开设计器文件后,将System.Windows.Forms.WebBrowser替换为MyExtendedBrowserControl。

建立项目。 您需要为要编译的控件执行此操作,并使其在表单本身上显示没有错误。

现在您构建了项目,您将能够编辑控件并访问新的WBWantsToClose事件。 打开表单,单击WebBrowser控件,打开其属性(F4),单击“事件”图标(闪电螺栓),双击“WBWantsToClose”。 这将带您进入准备好处理事件的代码。