如果我在我的应用程序中托管WebBrowser
,并且我的WebBrowser上显示的网页中的javascript代码调用了window.close()
,我在提示上单击“是”,我的WebBrowser
消失但我的形式保持开放。
我不想禁用javascript,而不是按“是”显然不是解决方案。处理这个问题的最佳方法是什么?即使用户按下“是”,这是否可以以编程方式取消?而且,还有其他任何javascript技巧,如window.close()
,可能会弄乱我的应用程序,我应该知道吗? (我的应用程序使用WebBrowser
来搜索网络,因此应该考虑每个可能的JavaScript代码。)
答案 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()时创建一个事件。
创建一个新的类文件并将以下代码放在
中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控件的Disposed或HandleDestroyed事件,以便关闭父窗体。对于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();
}
}