WebBrowser控件的简单应用
第一个简单应用里面讲述的是如何模拟调用当前网页的元素的事件或者赋值/取值。
这次的应用讲述的是
1:如何处理弹出新页面的事件(总是在我的浏览器里面现实新页面)
2:如何处理window.close事件,让我的浏览器页关闭
3:让html页面的js调用我的browse的函数
4:如何让我的browse调用html的js函数。
使用场景:一个web程序,让用户使用自定义浏览器来浏览,该web程序会调用浏览者机器上一些接口。
我的这个浏览器叫做AppBrowser。
关于ObjectForScripting 的介绍http://msdn2.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx
首先,第一个问题。
如果只是放置一个browse在那里,在html中打开新页面的时候,他默认使用IE或者其他浏览器来打开网页。如果想要让我的browse也同时能处理所有的新开页面,就要增加一个对_NewWindow事件的处理。
private void wb_Container_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true;
AppBrowser newAB = new AppBrowser(wb_Container.Url.ToString());
newAB.Show();
}
在这里要注意的是
1:e.Cancel = true;是为了取消这个事件,不然又打开一个IE
2:wb_Container.Url.接受到的是新页面的参数
关于关闭浏览器
通常,如果设置了这样的js:window.close,那么,IE会自动关闭。但是我的browse却不会,至少默认的是如此的。
为了关闭我的浏览器,我需要接收这个函数。但是,很可惜,找了半天都没找到这个事件在那里处理,于是结合下一个问题,一下子解决了。(其实是半个解决,只有自己写的web程序才能处理)。
关于web调用我的浏览器的函数。
这就成了web和win的交互了,这个win就是在客户端的。以前交互的方式是写一个ActiveX控件,让web调用他,进而访问客户机器上的一些资源。现在的这种方式则是通过自己提供一个符合COM接口的自定义browse来实现。
1:我的browse必须是符合COM接口的[System.Runtime.InteropServices.ComVisibleAttribute(true)]
2:设置一个属性 this.wb_Container.ObjectForScripting = this
这样,Web中就可以这样调用了javascript:window.external.xxx('xx')。比方说上边的那个关闭窗口的调用就可以这样写:
onclick="javascript:window.external.close();"
这个调用,其实是调用的我的browse的Close函数。这个函数是我的winForm上默认的那一个函数。调用其他函数亦然,只要是公开方法就可以。
关于如何browse调用web页面中的函数。
第一个,可以通过直接调用页面中元素的方式来实现,在我上一篇里面有所介绍。
第二个,就是可以直接访问.Document.InvokeScript函数来实现。
比如:
public object InvokeHtmlJsScript(string scriptName,object[] objects)
{
return this.wb_Container.Document.InvokeScript(scriptName, objects);
}
1 //set this class as a COM
2 [System.Runtime.InteropServices.ComVisibleAttribute(true)]
3 public partial class AppBrowser : Form
4 {
5 public AppBrowser()
6 {
7 InitializeComponent();
8 }
9 /// <summary>
10 /// which the url will be go
11 /// </summary>
12 /// <param name="url"></param>
13 public AppBrowser(string url)
14 {
15 InitializeComponent();
16 _url = url;
17 this.wb_Container.Navigate(_url);
18 this.wb_Container.ObjectForScripting = this;//set this to be the COM handler
19
20 }
21 private string _url;
22 public string Url
23 {
24 get { return this._url; }
25 }
26 /// <summary>
27 /// open new page in the window which is also in my brower but not in IE
28 /// </summary>
29 /// <param name="sender"></param>
30 /// <param name="e"></param>
31 private void wb_Container_NewWindow(object sender, CancelEventArgs e)
32 {
33 e.Cancel = true;
34 AppBrowser newAB = new AppBrowser(wb_Container.Url.ToString());
35 newAB.Show();
36 }
37 /// <summary>
38 /// this function can be invoked by js in html
39 /// like this 'javascript:window.external.ShowMessage('this is invoke from web');'
40 /// </summary>
41 /// <param name="msg"></param>
42 public void ShowMessage(string msg)
43 {
44 MessageBox.Show(msg);
45 }
46 /// <summary>
47 /// can invoke script in the html showing in the webbrowser
48 /// </summary>
49 /// <param name="scriptName"></param>
50 /// <param name="objects"></param>
51 /// <returns></returns>
52 public object InvokeHtmlJsScript(string scriptName,object[] objects)
53 {
54 return this.wb_Container.Document.InvokeScript(scriptName, objects);
55 }
56 }
后记:经过测试,终于找到了一种方法可以解决window.close的问题了(第二个问题)
2 {
3 wb_Container.Document.Window.Unload += new HtmlElementEventHandler(Window_Unload);
4 }
5
6 void Window_Unload(object sender, HtmlElementEventArgs e)
7 {
8 if (this.wb_Container.Document == null)
9 this.Close();
10 }
原理:
1:代理window的unload事件。这个事件在页面卸载的时候触发。
2:在这个事件之后检查webbrowser的值。如果是window.close,那么属性为空。
可能这个方法还是不够好,但是现下可用了。