Web浏览器和javascript window.close()

时间:2011-04-04 07:14:36

标签: c# .net browser

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

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

5 个答案:

答案 0 :(得分:5)

interface DWebBrowserEvents2有一个method WindowClosing可用于取消window.close()来电。

(我在this posting

中找到了建议

答案 1 :(得分:5)

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

答案 2 :(得分:1)

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

从这个页面,我得到了以下信息 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

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

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"。这将带您进入代码,并准备好处理事件。

答案 3 :(得分:0)

您使用的是哪个版本的WebBrowser控件? WinForms one或WPF one?

对于WinForms控件,您可以尝试处理WebBrowser控件的DisposedHandleDestroyed事件,以便关闭父窗体。对于WPF控件,您可以对Unloaded事件尝试相同的操作。

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

答案 4 :(得分:0)

我发现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();
        }
    }