這麼多篇關於WebBrowser之後,來一篇關於它的全面點的介紹
轉自http://blog.sina.com.cn/s/blog_3d7bed6501000c8n.html
WebBrowser控制項簡介 WebBrowser控制項由來以久,是一個ActiveX控制項。以前可以通過COM引用並使用。但在.Net Framework 2.0以後,提供了WebBrowser控制項的託管封裝。託管封裝使得在Windows表單用戶端中顯示網頁更為簡便。 使用WebBrowser控制項,可以模仿IE的功能進行Web訪問,但不僅僅局限於此,還可以通過禁用預設的IE功能,從而將該控制項用作簡單的HTML文檔查看器,甚至可以瀏覽Office各種格式文檔。 此外,WebBrowser支援DOM和文本兩種方式修改其承載的內容。這一點意味著沒有必要再把修改的HTML儲存到臨時檔案,而是直接在內容中實現修改並顯示,提高效能並節省臨時檔案資源消耗。 總而言之,我們可以通過種種方法,到達將Web控制項和Windows表單控制項無縫地整合到一個應用程式中的目的。
利用WebBrowser瀏覽網頁 瀏覽網頁是WebBrowser的老本行,託管封裝後的WebBrowser更加簡便易用。主要幾個方法如下:Navigate(): 導航頁面。與以前版本不同,可以只給定一個參數即可,即URI。GoBack() / GoForward() / GoHome(): 向後/向前/回首頁。 Stop():Refresh(): 停止載入/重新整理以上幾個主要方法是用於導航各個頁面用的,但它們並不是永遠生效。這些方法是否生效,取決於AllowNavigation屬性,預設為true,允許導航。Print():用於列印。
(1)WebBrowser中的Html文檔模型 我們可以通過DOM或文本的形式返回當前WebBrowser中的HTML文檔: Document: DOM(文件物件模型)形式的對當前網頁的HTML描述。 DocumentText: 文本形式的對當前網頁的HTML描述。 DocumentStream: 流形式的HTML描述。 關於文本形式的沒有什麼好說的,它是最直接的HTML描述,但是難於動態修改,而相比之下DOM形式的HTML描述則靈活的多,可以任意添加、修改、刪除任意節點。DOM物件模型主要元素有HtmlDocument, HtmlElement, HtmlNode, HtmlText等等,在此不再囉嗦了。
(2)WebBrowser與IE 預設情況下,WebBrowser控制項功能於IE極其相似,提供準系統。如:可以通過GoHome(),GoBack(),GoFoward(),Stop(),Refresh()來實現IE工具列中的首頁、向後、向前、停止、重新整理;通過Navigate()來實現IE中的地址欄;通過設定IsWebBrowserContextMenuEnabled = true來實現IE右鍵菜單;通過設定WebBrowserShortcutsEnabled = true來實現IE的快速鍵等等。 同樣在某些特殊需要下,我們可能不希望WebBrowser的行為與IE一樣,比如我們只是希望WebBrowser作為一個Html的顯示器,在這種情況下可把AllowNavigate設定成false來阻止WebBrowser的導航功能;把IsWebBrowserContextMenuEnabled和WebBrowserShortcutsEnabled設定為false來阻止右鍵菜單和快速鍵等等。從而阻止了WebBrowser的一些IE特性。
(3)WebBrowser中的指令碼錯誤處理 當IE瀏覽器遇到時指令碼錯誤,左下角會出現一個黃色表徵圖,點擊可以查看指令碼錯誤的詳細資料,並不會有彈出的錯誤資訊框。但是WebBrowser控制項則沒有這麼聰明,它會彈出錯誤資訊框,使得程式顯的很不友好,而且會讓一些自動執行的程式暫停。雖然WebBrowser提供了ScriptErrorsSuppressed屬性,經過嘗試,結果是令人遺憾的,通過設定該屬性可以解決部分問題,但不能徹底解決。在此探討兩種解決方案:一是通過截獲WebBrowser.Document.Window.Error事件,並阻止WebBrowser繼續處理錯誤來解決。如下: //註冊捕獲控制項的錯誤的處理事件
this.WebBrowser.Document.Window.Error += new HtmlElementErrorEventHandler(Window_Error);
//對錯誤進行處理
void Window_Error(object sender, HtmlElementErrorEventArgs e)
{
e.Handled = true; // 阻止其他地方繼續處理
}
上面的方法可以解決大部分問題,但對於多個架構嵌套等等的情形還是不能很好的解決,於是只能自己動手封裝一個MyWebBrowser了,然後用我們自己的MyWebBrowser來替代WebBrowser。如下:
public class MyWebBrowser : System.Windows.Forms.WebBrowser
{
private SHDocVw.IWebBrowser2 Iwb2;
protected override void AttachInterfaces(object nativeActiveXObject)
{
Iwb2 = (SHDocVw.IWebBrowser2) nativeActiveXObject;
Iwb2.Silent = true;
base.AttachInterfaces(nativeActiveXObject);
}
protected override void DetachInterfaces()
{
Iwb2 = null;
base.DetachInterfaces();
}
}
這種方法能能很好的解決問題,其實使用過非託管WebBrowser的朋友肯定看出來了,實際上是通過引用SHDocVw繞過Managed 程式碼,直接SHDocVw.IWebBrowser2.Silent = true,最原始的也是最有效。
利用WebBrowser訪問Office檔案 剛剛說過瀏覽網頁是WebBrowser的老本行,那麼除了本行外,其實他還可以搞點兼職。我們知道,在.Net表單中是不提供嵌入Office文檔OLE控制項的,如果希望嵌Office文檔的話,一個可能的解決方案就是使用WebBrowser控制項。 其實在IE中就可以嵌入Office文檔,所以WebBrowser具有此功力也很正常,但它帶來的效果確實不錯。操作也很簡單: this.webBrowser1.Navigate(strFileName);只此一句,WebBrowser就會以嵌入的形式開啟Office文檔(Word, Excel, PowerPoint,...)了,效果如:
使用 WebBrowser 控制項時的注意事項 1、在NET 2.0下的Webbrowser控制項是對Webbrowser COM組件的不完全封裝。所以,在簡便的同時也會出現這樣或那樣的問題。簡便也是有代價的。 2、WebBrowser控制項非同步瀏覽到文檔。在調用Navigate()時,該調用會在文檔完全載入之前將控制權返回給應用程式。如果打算為所包含的文檔實現自動操作,則必須在DocumentCompleted事件在文檔完成載入後發出通知。或是通過IsBusy來判斷當前WebBrowser是否正忙於載入其他文檔。 然而,通過實踐,問題卻不是這麼簡單。一般情況下,當ReadyState屬性變成READYSTATE_COMPLETE時,Webbrowser控制項會通過觸發DocumentCompleted事件來指示網頁載入完畢。但當載入的網頁包含frame時,可能會多次觸發該事件,所以不能簡單地通過它來判斷網頁載入完畢。並非每個frame都對應了一個DocumentCompleted事件,只有觸發了DownloadBegin事件的frame才會有相應的DocumentCompleted事件。另外,最外層的frame總是最後觸發DocumentCompleted事件。那麼怎麼準確的判斷頁面載入完畢了呢,以下為一方案:
int counter = 0 ; // 計數器
private void webBrowser_Navigated(object sender,
WebBrowserNavigatedEventArgs e){
counter ++ ;
}
private void webBrowser_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e){
counter -- ;
if (counter == 0){
// 載入完畢
}
}
3、在一個項目中有多個WebBrowser控制項並且每個控制項都載入相同類型的Office文檔(全都是Word或全都是Excel)時,會出現多種問題。最常見的問題發生在Office命令欄上(命令欄會被禁用)。如果在同一個表單上有兩個WebBrowser控制項,且兩個控制項都載入Word文檔,那麼只有一組工具列會是活動的,另外一個則被禁用,無法使用。所以,建議一個項目只使用一個控制項,並且一次只瀏覽到一個文檔。
4、要清除WebBrowser控制項中的當前內容,使用下面的代碼瀏覽到預設空白頁:
this.webBrowser1.Navigate("about:blank");