在开发Windows Forms应用程序时,经常需要在桌面应用中嵌入Web浏览功能。本文将探讨如何使用WebBrowser控件处理一些常见的问题,例如JavaScript中的window.close()调用和新窗口的打开事件。这些问题在开发具有标签浏览功能的应用程序时尤为重要。
在创建公司内部使用的桌面应用程序时,遇到了上述问题。该应用程序的主要目的是允许在两个Web页面之间进行修改后的复制粘贴操作。如果没有频繁地打开新窗口和调用JavaScriptwindow.close(),这个问题本可以很容易解决。
在创建标签浏览界面后,发现当页面尝试打开一个新窗口时,会打开一个全新的窗口。这主要的问题是,正在浏览的网站需要用户名和密码登录,这意味着当打开IE实例时,用户需要再次登录,因为IE是在不同的线程中执行的(这可能会干扰与用户名/密码相关的cookie)。
最初的想法是使用WebBrowser的NewWindow事件,捕获URL,并在新标签页中打开它。然而,这就是问题所在...NewWindow事件提供了CancelEventArgs,允许通过设置e.Cancel为true来阻止新窗口的打开,但它没有提供更多有用的信息,如URL等。
在浏览了一些网络资源后,发现了一个更简单的方法来获取更广泛的事件。首先,需要在项目中添加一个COM引用'Microsoft Internet Controls'。然后,在代码文件中添加using SHDocVw;。这个命名空间让可以访问SHDocVw.WebBrowser,这是需要的类。
System.Windows.Forms.WebBrowser控件有一个名为ActiveXInstance的属性,类型为object。只需要将ActiveXInstance属性转换为SHDocVw.WebBrowser,就可以访问ActiveX浏览器提供的完整事件范围,包括NewWindow3,它提供了更多的事件参数,包括URL。
System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
SHDocVw.WebBrowser axBrowser = (SHDocVw.WebBrowser)webBrowser.ActiveXInstance;
axBrowser.NewWindow3 += new DWebBrowserEvents2_NewWindow3EventHandler(Browser_NewWindow3);
以上代码展示了如何为NewWindow3事件分配一个事件处理程序。
在解决了新窗口问题后,很快遇到了第二个问题。当通过JavaScript关闭窗口时,WebBrowser控件会挂起。这次想,已经通过ActiveX浏览器获得了很多事件,只需要找到一个窗口关闭/已关闭事件,并在其中执行所需的操作。
然而,尽管有一个WindowClosing事件,但它在调用JavaScript window.close()时不会被触发。不知道为什么,在网上找到的其他人也不知道。尽管如此,还是有办法解决这个问题的!
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PARENTNOTIFY:
if (!DesignMode)
{
if (m.WParam.ToInt32() == WM_DESTROY)
{
Message newMsg = new Message();
newMsg.Msg = WM_DESTROY;
TabPage parentTab = this.Parent as TabPage;
if (parentTab != null)
{
TabControl browserTabs = parentTab.Parent as TabControl;
if (browserTabs != null)
{
browserTabs.TabPages.Remove(parentTab);
}
}
}
}
DefWndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
using System;
using System.Windows.Forms;
namespace GoldMedal.TravelinkViewer.UI.User_Controls
{
public class ExtendedWebBrowser : WebBrowser
{
private const int WM_PARENTNOTIFY = 0x210;
private const int WM_DESTROY = 2;
public SHDocVw.WebBrowser ActiveXBrowser
{
get { return (SHDocVw.WebBrowser)ActiveXInstance; }
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PARENTNOTIFY:
if (!DesignMode)
{
if (m.WParam.ToInt32() == WM_DESTROY)
{
Message newMsg = new Message();
newMsg.Msg = WM_DESTROY;
TabPage parentTab = this.Parent as TabPage;
if (parentTab != null)
{
TabControl browserTabs = parentTab.Parent as TabControl;
if (browserTabs != null)
{
browserTabs.TabPages.Remove(parentTab);
}
}
}
}
DefWndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
}
}