WebBrowser页面与WinForm交互技巧
話說有了WebBrowser類,終于不用自己手動封裝SHDocVw的AxWebBrowser這個ActiveX控件了。這個類如果僅僅作為一個和IE一模一樣瀏覽器,那就太沒意思了(還不如直接用IE呢)。那么,無論我們是想做一個“定制版IE”,還是希望利用HTML來做用戶界面(指WinApp而非WebApp。許多單機(jī)軟件,包括Windows的幫助支持中心,都是HTML做的),都少不了Windows?Form和包含在WebBrowser中的Web頁面的交互。本文將通過幾個實(shí)際的例子,初步介紹一下WinForm和WebBrowser所包含的Web頁面之間的交互。
下面的代碼假設(shè)你已經(jīng)建立了一個Windows?Form,上面有一個WebBrowser名為“webBrowser”。
Study?Case?1:用WinForm的Event?Handler響應(yīng)Web頁面的事件
現(xiàn)在有這樣一個Windows?Application,它的界面上只有一個WebBrowser,顯示一個本地的HTML文件作為界面。現(xiàn)在的問題是,所有邏輯都可以放在HTML文件里,唯獨(dú)“關(guān)閉”按鈕遇到了困難——通常,Web頁面是沒有辦法直接控制瀏覽器的,更不用說結(jié)束這個WinForm程序了。
但是,在.Net?2.0當(dāng)中,“由Windows?Form響應(yīng)Web頁面的事件”已經(jīng)成為了現(xiàn)實(shí)。
在.Net?2.0中,整個HTML文檔以及其包含的各個HTML元素,都和一個個HtmlDocument、HtmlElement之類的.Net對象對應(yīng)。因此只要找到這個“關(guān)閉”按鈕對應(yīng)的HtmlElement對象,為其click事件添加Event?Handler即可。?
假設(shè)HTML源代碼如下:?
那么找出該按鈕并為之添加Event?Handler的代碼如下:
HtmlDocument htmlDoc = webBrowser.Document; HtmlElement btnElement = htmlDoc.All["btnClose"]; if (btnElement != null) {btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click); }其中HtmlBtnClose_Click是按下Web按鈕時的Event?Handler。?
很簡單吧?那么稍稍高級一點(diǎn)的——我們都知道一個HTML元素可能有很多各種各樣的事件,而HtmlElement這個類只給出最常用、共通的幾個。那么,如何響應(yīng)其他事件呢?這也很簡單,只需要調(diào)用HtmlElement的AttachEventHandler就可以了:
對于其他事件,把"onclick"換成該事件的名字就可以了。例如:
formElement.AttachEventHandler("onsubmit", new EventHandler(HtmlForm_Submit));Study?Case?2:表單(form)的自動填寫和提交
要使我們的WebBrowser具有自動填表、甚至自動提交的功能,并不困難。?
假設(shè)有一個最簡單的登錄頁面,輸入用戶名密碼,點(diǎn)“登錄”按鈕即可登錄。已知用戶名輸入框的id(或Name,下同)是username,密碼輸入框的id是password,“登錄”按鈕的id是submitbutton,那么我們只需要在webBrowser的DocumentCompleted事件中使用下面的代碼即可:
這里我們用SetAttribute來設(shè)置文本框的“value”屬性,用InvokeMember來調(diào)用了按鈕的“click”方法。因?yàn)椴煌腍tml元素,其擁有的屬性和方法也不盡相同,所以.Net?2.0提供了統(tǒng)一的HtmlElement來概括各種Html元素的同時,提供了這兩個方法以調(diào)用元素特有的功能。關(guān)于各種Html元素的屬性和方法一覽,可以查閱MSDN的DHTML?Reference。?
http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp
※關(guān)于表單的提交,的確還有另一種方法就是獲取form元素而不是button,并用form元素的submit方法:
本文之所以沒有推薦這種方法,是因?yàn)楝F(xiàn)在的網(wǎng)頁,很多都在submit按鈕上添加onclick事件,以對提交的內(nèi)容做最基本的驗(yàn)證。如果直接使用form的submit方法,這些驗(yàn)證代碼就得不到執(zhí)行,有可能會引起錯誤。?
Study?Case?3:查找并選擇文本
這次我們希望實(shí)現(xiàn)一個和IE一模一樣的查找功能,以對Web頁面內(nèi)的文字進(jìn)行查找。?
文本查找要借助于TextRange對象的findText方法。但是,.Net里并沒有這個對象。這是因?yàn)?#xff0c;.Net?2.0提供的HtmlDocument,HtmlWindow,HtmlElement等類,只不過是對原有mshtml這個COM組件的不完整封裝,只提供了mshtml的部分功能。所以許多時候,我們?nèi)耘f要借助mshtml來實(shí)現(xiàn)我們需要的功能。好在這些.Net類都提供了DomDocument這個屬性,使得我們很容易把.Net對象轉(zhuǎn)換為COM對象使用。下面的代碼演示了如何查找Web頁面的文本。?
(需要添加mshtml的引用,并加上using?mshtml;)
到此為止,簡單的查找就搞定了。至于替換功能,看了下一個例子,我相信你就可以觸類旁通輕松搞定了。?
Study?Case?4:高亮顯示
上一個例子中我們學(xué)會了查找文本——究跟到底,對Web頁面還是只讀不寫。那么,如果說要把所有的搜索結(jié)果高亮顯示呢?我們很快會想到把所有匹配的文字顏色、背景改一下就可以了。?
首先想到的可能是直接修改HTML文本吧……但是,與SourceCode的高亮顯示不同,我們需要并且只需要高亮頁面中的文本部分。HTML標(biāo)簽、腳本代碼等等是絕對不應(yīng)該去改動的。因此我們不能把整個頁面的Source?Code讀進(jìn)來然后replace,那樣有破壞HTML文件結(jié)構(gòu)的可能;我們只能在能夠分離出文本與其他內(nèi)容(標(biāo)簽,腳本……)的前提下進(jìn)行。?
具體方法有很多,下面提供兩個比較簡單的方法。?
方法一:使用TextRange(IHTMLTxtRange)?
有了上一個Case的基礎(chǔ),相信大家立刻會想到使用TextRange。沒錯,TextRange除了提供查找方法之外,還提供了一個pasteHTML方法,以指定的HTML文本替換當(dāng)前TextRange中的內(nèi)容。代碼片斷如下:
※這段代碼里獲取IHTMLTxtRange的方式和上面的例子稍稍不同,其實(shí)所謂條條大路通羅馬,本質(zhì)是一樣的。?
方法二:使用DOM(文檔對象模型)?
將HTML文檔解析為DOM,然后遍歷每個節(jié)點(diǎn),在其中搜索關(guān)鍵字并進(jìn)行相應(yīng)替換處理即可。
上面的兩段代碼都是為了清晰易懂而精簡得不能再簡的,有很多地方很不完善。比如,沒考慮到如何從高亮顯示狀態(tài)復(fù)原;也沒有大小寫匹配等等。當(dāng)然,掌握了原理之后相信這些都不會太難。?
這兩種方法各有優(yōu)缺點(diǎn):?
使用TextRange較輕量迅速,而且有一個特長,就是可以把跨標(biāo)簽(Tag)的關(guān)鍵字挑出來。例如,有這么一段HTML:
先不管作者出于什么目的讓Hel三個字母成為粗體,總之顯示在頁面上的是一句“Hello?World!”。在我們希望高亮頁面中的“Hello”這個關(guān)鍵字時,如果用DOM分析的話,會得出含有“Hel”的<b>節(jié)點(diǎn)和文本節(jié)點(diǎn)“l(fā)o?World!”兩個節(jié)點(diǎn),因此無法將其挑出來。而TextRange則能正確識別,將其設(shè)置為高亮。因此也可以說TextRange是只和文本有關(guān),和HTML語法結(jié)構(gòu)無關(guān)的對象。?
但是,TextRange也有其致命缺點(diǎn),加亮容易,反向的話就很難。換句話說,去除高亮顯示的時候不能再用TextRange,而需要采用其他方法。?
而DOM方法則正好相反,?由于DOM的樹狀結(jié)構(gòu)特性,雖然不能(或者很難)跨越Tag搜索關(guān)鍵字,但是去除高亮顯示并不繁瑣。
Study?Case?5:與腳本的互操作?
在Case?1當(dāng)中,我們已經(jīng)看到,Web頁面的HTML元素的事件,可以由Windows?Form端來響應(yīng),可以在某種程度上看作是Web頁面調(diào)用WinForm;那么反過來,WinForm除了可以直接訪問Web頁面的HTML元素之外,能否調(diào)用Web頁面里的各種Script呢?
首先是調(diào)用Web頁面的腳本中已經(jīng)定義好的函數(shù)。假設(shè)HTML中有如下Javascript:
那么,我們要在WinForm調(diào)用它,只需如下代碼即可:
object oSum = webBrowser.Document.InvokeScript("DoAdd", new object[] { 1, 2 }); int sum = Convert.ToInt32(oSum);其次,如果我們想執(zhí)行一段Web頁面中原本沒有的腳本,該怎么做呢?這次.Net的類沒有提供,看來還要依靠COM了。IHTMLWindow2可以將任意的字符串作為腳本代碼來執(zhí)行。
string scriptline01 = @"function ShowPageInfo() {"; string scriptline02 = @" var numLinks = document.links.length; "; string scriptline03 = @" var numForms = document.forms.length; "; string scriptline04 = @" var numImages = document.images.length; "; string scriptline05 = @" var numScripts = document.scripts.length; "; string scriptline06 = @" alert('網(wǎng)頁的統(tǒng)計結(jié)果:\r\n鏈接數(shù):' + numLinks + "; string scriptline07 = @" '\r\n表單數(shù):' + numForms + "; string scriptline08 = @" '\r\n圖像數(shù):' + numImages + "; string scriptline09 = @" '\r\n腳本數(shù):' + numScripts);}"; string scriptline10 = @"ShowPageInfo();";string strScript = scriptline01 + scriptline02 + scriptline03 + scriptline04 + scriptline05 +scriptline06 + scriptline07 + scriptline08 + scriptline09 + scriptline10;IHTMLWindow2 win = (IHTMLWindow2)webBrowser.Document.Window.DomWindow; win.execScript(strScript, "Javascript");?
轉(zhuǎn)載于:https://www.cnblogs.com/DoNetCShap/archive/2012/06/26/2564498.html
總結(jié)
以上是生活随笔為你收集整理的WebBrowser页面与WinForm交互技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转载]细说ASP.NET Window
- 下一篇: 转:STL:string 大小(Size