第一個簡單應用裡面講述的是如何模拟調用目前網頁的元素的事件或者指派/取值。
這次的應用講述的是
1:如何處理彈出新頁面的事件(總是在我的浏覽器裡面現實新頁面)
2:如何處理window.close事件,讓我的浏覽器頁關閉
3:讓html頁面的js調用我的browse的函數
4:如何讓我的browse調用html的js函數。
使用場景:一個web程式,讓使用者使用自定義浏覽器來浏覽,該web程式會調用浏覽者機器上一些接口。
我的這個浏覽器叫做AppBrowser。
首先,第一個問題。
如果隻是放置一個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
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
27
/// open new page in the window which is also in my brower but not in IE
28
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
38
/// this function can be invoked by js in html
39
/// like this 'javascript:window.external.ShowMessage('this is invoke from web');'
40
41
/// <param name="msg"></param>
42
public void ShowMessage(string msg)
43
44
MessageBox.Show(msg);
45
46
47
/// can invoke script in the html showing in the webbrowser
48
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的問題了(第二個問題)
private void wb_Container_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

wb_Container.Document.Window.Unload += new HtmlElementEventHandler(Window_Unload);
void Window_Unload(object sender, HtmlElementEventArgs e)

if (this.wb_Container.Document == null)
this.Close();
原理:
1:代理window的unload事件。這個事件在頁面解除安裝的時候觸發。
2:在這個事件之後檢查webbrowser的值。如果是window.close,那麼屬性為空。
可能這個方法還是不夠好,但是現下可用了。