[轉]讀取webBrowser中網頁程式碼
DataTable dtt = new DataTable();
dtt=dt.Clone();//拷貝框架
DataRow[] dr = dt.select("條件");
for(int i=0;i<dr.length;i++)
{
dtt.ImportRow((DataRow)dr[i]);//
}
this.DataGrid.DataSource=dtt;
this.DataGrid.DataBind();
******************************************
(FileSaveMode)Enum.Parse(typeof(FileSaveMode), attributeCollection["AttachmentSaveMode"].Value);
******************************************
//不能用 this.webBrowser.DocumentText 讀取網頁原始碼,讀出來是亂碼
string url="http://www.yn-home.com";
this.webBrowser.Url = new System.Uri(url);
System.IO.StreamReader strm = new System.IO.StreamReader(this.webBrowser.DocumentStream, Encoding.GetEncoding("gb2312"));
string docment = strm.ReadToEnd();
// MessageBox.Show(strm.ReadToEnd());
******************************************
這是在CSDN論壇上的一個問題,感覺也許對其他人也會有點用處,所以貼出來
JScript是建立在COM之上的,設定變數/呼叫函式是通過IDispatch來實現的。在.NET裡,呼叫IDispatch裡的方法是通過反射來實現的,即,通過System.Type.InvokeMember 。該方法呼叫 IDispatch::GetIDsOfNames 以及IDispatch::Invoke來呼叫COM Automation 物件裡的方法和屬性。參考
Binding for Office automation servers with Visual C# .NET
假如有下列HTML,
<script language="javascript">
var var1 = 'yes';
function testx(obj)
{
alert(obj);
alert(var1);
}
</script>
<input type=button value="click me" onclick="testx('hello');">
在C#裡,假設axWebBrowser1是你的WebBrowser控制元件物件,你已經裝載了上述HTML,你可以這麼做,
mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)axWebBrowser1.Document;
mshtml.IHTMLWindow2 win = (mshtml.IHTMLWindow2)doc.parentWindow;
//讀變數值
object o = win.GetType().InvokeMember ("var1", BindingFlags.GetProperty, null, win, new Object [] {});
//寫變數值
win.GetType().InvokeMember ("var1", BindingFlags.SetProperty, null, win, new Object [] {"新的值"});
//呼叫方法
win.GetType().InvokeMember("testx",BindingFlags.InvokeMethod,null,win,new object[]{1});
比較麻煩,對麼?幸運的是,我們不用這麼麻煩,因為IHTMLWindow2裡有個現成方法,execScript,我們可以這麼做:
win.execScript("var1 = 'abc';","javascript");
win.execScript("testx(12)","javascript");
****************************************************
最近看到部落格園入門教學文章比較流行,自己最近又偷懶比較多,沒啥心得,不妨寫一篇沒啥深度的入門文章吧。
話說有了WebBrowser類,終於不用自己手動封裝SHDocVw的AxWebBrowser這個ActiveX控制元件了。這個類如果僅僅作為一個和IE一模一樣瀏覽器,那就太沒意思了(還不如直接用IE呢)。那麼,無論我們是想做一個“定製版IE”,還是希望利用HTML來做使用者介面(指WinApp而非WebApp。許多單機軟體,包括Windows的幫助支援中心,都是HTML做的),都少不了Windows Form和包含在WebBrowser中的Web頁面的互動。本文將通過幾個實際的例子,初步介紹一下WinForm和WebBrowser所包含的Web頁面之間的互動。
下面的程式碼假設你已經建立了一個Windows Form,上面有一個WebBrowser名為“webBrowser”。
Study Case 1:用WinForm的Event Handler響應Web頁面的事件
現在有這樣一個Windows Application,它的介面上只有一個WebBrowser,顯示一個本地的HTML檔案作為介面。現在的問題是,所有邏輯都可以放在HTML檔案裡,唯獨“關閉”按鈕遇到了困難——通常,Web頁面是沒有辦法直接控制瀏覽器的,更不用說結束這個WinForm程式了。
但是,在.Net 2.0當中,“由Windows Form響應Web頁面的事件”已經成為了現實。
在.Net 2.0中,整個HTML文件以及其包含的各個HTML元素,都和一個個HtmlDocument、HtmlElement之類的.Net物件對應。因此只要找到這個“關閉”按鈕對應的HtmlElement物件,為其click事件新增Event Handler即可。
假設HTML原始碼如下:
<body>
<input type="button" id="btnClose" value="關閉" />
</body>
</html>
那麼找出該按鈕併為之新增Event Handler的程式碼如下:
HtmlElement btnElement = htmlDoc.All["btnClose"];
if (btnElement != null)
{
btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
}
其中HtmlBtnClose_Click是按下Web按鈕時的Event Handler。
很簡單吧?那麼稍稍高階一點的——我們都知道一個HTML元素可能有很多各種各樣的事件,而HtmlElement這個類只給出最常用、共通的幾個。那麼,如何響應其他事件呢?這也很簡單,只需要呼叫HtmlElement的AttachEventHandler就可以了:
//這一句等價於上面的btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
對於其他事件,把"onclick"換成該事件的名字就可以了。例如:
Study Case 2:表單(form)的自動填寫和提交
要使我們的WebBrowser具有自動填表、甚至自動提交的功能,並不困難。
假設有一個最簡單的登入頁面,輸入使用者名稱密碼,點“登入”按鈕即可登入。已知使用者名稱輸入框的id(或Name,下同)是username,密碼輸入框的id是password,“登入”按鈕的id是submitbutton,那麼我們只需要在webBrowser的DocumentCompleted事件中使用下面的程式碼即可:
HtmlElement tbUserid = webBrowser.Document.All["username"];
HtmlElement tbPasswd = webBrowser.Document.All["password"];
if (tbUserid == null || tbPasswd == null || btnSubmit == null)
return;
tbUserid.SetAttribute("value", "smalldust");
tbPasswd.SetAttribute("value", "12345678");
btnSubmit.InvokeMember("click");
這裡我們用SetAttribute來設定文字框的“value”屬性,用InvokeMember來呼叫了按鈕的“click”方法。因為不同的Html元素,其擁有的屬性和方法也不盡相同,所以.Net 2.0提供了統一的HtmlElement來概括各種Html元素的同時,提供了這兩個方法以呼叫元素特有的功能。關於各種Html元素的屬性和方法一覽,可以查閱MSDN的DHTML Reference。
※關於表單的提交,的確還有另一種方法就是獲取form元素而不是button,並用form元素的submit方法:
//……
formLogin.InvokeMember("submit");
本文之所以沒有推薦這種方法,是因為現在的網頁,很多都在submit按鈕上新增onclick事件,以對提交的內容做最基本的驗證。如果直接使用form的submit方法,這些驗證程式碼就得不到執行,有可能會引起錯誤。
Study Case 3:查詢並選擇文字
這次我們希望實現一個和IE一模一樣的查詢功能,以對Web頁面內的文字進行查詢。
文字查詢要藉助於TextRange物件的findText方法。但是,.Net裡並沒有這個物件。這是因為,.Net 2.0提供的HtmlDocument,HtmlWindow,HtmlElement等類,只不過是對原有mshtml這個COM元件的不完整封裝,只提供了mshtml的部分功能。所以許多時候,我們仍舊要藉助mshtml來實現我們需要的功能。好在這些.Net類都提供了DomDocument這個屬性,使得我們很容易把.Net物件轉換為COM物件使用。下面的程式碼演示瞭如何查詢Web頁面的文字。
(需要新增mshtml的引用,並加上using mshtml;)
{
// 建立一個查詢用的TextRange(IHTMLTxtRange介面)
private IHTMLTxtRange searchRange = null;
public SearchDemo()
{
InitializeComponent();
}
private void btnSearch_Click(object sender, EventArgs e)
{
// Document的DomDocument屬性,就是該物件內部的COM物件。
IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document.DomDocument;
string keyword = txtKeyword.Text.Trim();
if (keyword == "")
return;
// IE的查詢邏輯就是,如果有選區,就從當前選區開頭+1字元處開始查詢;沒有的話就從頁面最初開始查詢。
// 這個邏輯其實是有點不大恰當的,我們這裡不用管,和IE一致即可。
if (document.selection.type.ToLower() != "none")
{
searchRange = (IHTMLTxtRange)document.selection.createRange();
searchRange.collapse(true);
searchRange.moveStart("character", 1);
}
else
{
IHTMLBodyElement body = (IHTMLBodyElement)document.body;
searchRange = (IHTMLTxtRange)body.createTextRange();
}
// 如果找到了,就選取(高亮顯示)該關鍵字;否則彈出訊息。
if (searchRange.findText(keyword, 1, 0))
{
searchRange.select();
}
else
{
MessageBox.Show("已搜尋到文件結尾。");
}
}
}
到此為止,簡單的查詢就搞定了。至於替換功能,看了下一個例子,我相信你就可以觸類旁通輕鬆搞定了。
Study Case 4:高亮顯示
上一個例子中我們學會了查詢文字——究跟到底,對Web頁面還是隻讀不寫。那麼,如果說要把所有的搜尋結果高亮顯示呢?我們很快會想到把所有匹配的文字顏色、背景改一下就可以了。
首先想到的可能是直接修改HTML文字吧……但是,與SourceCode的高亮顯示不同,我們需要並且只需要高亮頁面中的文字部分。HTML標籤、指令碼程式碼等等是絕對不應該去改動的。因此我們不能把整個頁面的Source Code讀進來然後replace,那樣有破壞HTML檔案結構的可能;我們只能在能夠分離出文字與其他內容(標籤,指令碼……)的前提下進行。
具體方法有很多,下面提供兩個比較簡單的方法。
方法一:使用TextRange(IHTMLTxtRange)
有了上一個Case的基礎,相信大家立刻會想到使用TextRange。沒錯,TextRange除了提供查詢方法之外,還提供了一個pasteHTML方法,以指定的HTML文字替換當前TextRange中的內容。程式碼片斷如下:
{
// 定義高亮顯示效果的標籤。
string tagBefore = "<span style='background-color:yellow;color:black'>";
string tagAfter = "</span>";
// ……
private void btnHilight_Click(object sender, EventArgs e)
{
HtmlDocument htmlDoc = webBrowser.Document;
string keyword = txtKeyword.Text.Trim();
if (keyword == "")
return;
object oTextRange = htmlDoc.Body.InvokeMember("createTextRange");
mshtml.IHTMLTxtRange txtrange = oTextRange as mshtml.IHTMLTxtRange;
while (txtrange.findText(keyword, 1, 4))
{
try
{
txtrange.pasteHTML(tagBefore + keyword + tagAfter);
}
catch { }
txtrange.collapse(false);
}
}
}
※這段程式碼裡獲取IHTMLTxtRange的方式和上面的例子稍稍不同,其實所謂條條大路通羅馬,本質是一樣的。
方法二:使用DOM(文件物件模型)
將HTML文件解析為DOM,然後遍歷每個節點,在其中搜尋關鍵字並進行相應替換處理即可。
{
//……
private void btnHilight_Click(object sender, EventArgs e)
{
HTMLDocument document = (HTMLDocument)webBrowser.Document.DomDocument;
IHTMLDOMNode bodyNode = (IHTMLDOMNode)webBrowser.Document.Body.DomElement;
string keyword = txtKeyword.Text.Trim();
if (keyword == "")
return;
HilightText(document, bodyNode, keyword);
}
private void HilightText(HTMLDocument document, IHTMLDOMNode node, string keyword)
{
// nodeType = 3:text節點
if (node.nodeType == 3)
{
string nodeText = node.nodeValue.ToString();
// 如果找到了關鍵字
if (nodeText.Contains(keyword))
{
IHTMLDOMNode parentNode = node.parentNode;
// 將關鍵字作為分隔符,將文字分離,並逐個新增到原text節點的父節點
string[] result = nodeText.Split(new string[] { keyword }, StringSplitOptions.None);
for (int i = 0; i < result.Length - 1; i++)
{
if (result[i] != "")
{
IHTMLDOMNode txtNode = document.createTextNode(result[i]);
parentNode.insertBefore(txtNode, node);
}
IHTMLDOMNode orgNode = document.createTextNode(keyword);
IHTMLDOMNode hilightedNode = (IHTMLDOMNode)document.createElement("SPAN");
IHTMLStyle style = ((IHTMLElement)hilightedNode).style;
style.color = "black";
style.backgroundColor = "yellow";
hilightedNode.appendChild(orgNode);
parentNode.insertBefore(hilightedNode, node);
}
if (result[result.Length - 1] != "")
{
IHTMLDOMNode postNode = document.createTextNode(result[result.Length - 1]);
parentNode.insertBefore(postNode, node);
}
parentNode.removeChild(node);
} // End of nodeText.Contains(keyword)
}
else
{
// 如果不是text節點,則遞迴搜尋其子節點
IHTMLDOMChildrenCollection childNodes = node.childNodes as IHTMLDOMChildrenCollection;
foreach (IHTMLDOMNode n in childNodes)
{
HilightText(document, n, keyword);
}
}
}
}
上面的兩段程式碼都是為了清晰易懂而精簡得不能再簡的,有很多地方很不完善。比如,沒考慮到如何從高亮顯示狀態復原;也沒有大小寫匹配等等。當然,掌握了原理之後相信這些都不會太難。
這兩種方法各有優缺點:
使用TextRange較輕量迅速,而且有一個特長,就是可以把跨標籤(Tag)的關鍵字挑出來。例如,有這麼一段HTML:
先不管作者出於什麼目的讓Hel三個字母成為粗體,總之顯示在頁面上的是一句“Hello World!”。在我們希望高亮頁面中的“Hello”這個關鍵字時,如果用DOM分析的話,會得出含有“Hel”的<b>節點和文字節點“lo World!”兩個節點,因此無法將其挑出來。而TextRange則能正確識別,將其設定為高亮。因此也可以說TextRange是隻和文字有關,和HTML語法結構無關的物件。
但是,TextRange也有其致命缺點,加亮容易,反向的話就很難。換句話說,去除高亮顯示的時候不能再用TextRange,而需要採用其他方法。
而DOM方法則正好相反, 由於DOM的樹狀結構特性,雖然不能(或者很難)跨越Tag搜尋關鍵字,但是去除高亮顯示並不繁瑣。
Study Case 5:與指令碼的互操作
在Case 1當中,我們已經看到,Web頁面的HTML元素的事件,可以由Windows Form端來響應,可以在某種程度上看作是Web頁面呼叫WinForm;那麼反過來,WinForm除了可以直接訪問Web頁面的HTML元素之外,能否呼叫Web頁面裡的各種Script呢?
首先是呼叫Web頁面的指令碼中已經定義好的函式。假設HTML中有如下Javascript:
return a + b;
}
那麼,我們要在WinForm呼叫它,只需如下程式碼即可:
int sum = Convert.ToInt32(oSum);
其次,如果我們想執行一段Web頁面中原本沒有的指令碼,該怎麼做呢?這次.Net的類沒有提供,看來還要依靠COM了。IHTMLWindow2可以將任意的字串作為指令碼程式碼來執行。
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('網頁的統計結果:/r/n連結數:' + numLinks + ";
string scriptline07 = @" '/r/n表單數:' + numForms + ";
string scriptline08 = @" '/r/n影象數:' + numImages + ";
string scriptline09 = @" '/r/n指令碼數:' + 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");
轉自:http://www.cnblogs.com/n1980212/archive/2006/11/29/576492.html
相關文章
- 使用WebBrowser控制元件獲取網頁原始碼的方法Web控制元件網頁原始碼
- webbrowser 控制 頁面Web
- windowsphone中WebBrowser中的頁面按級回退功能WindowsWeb
- 分頁按頁碼讀取redis資料Redis
- 在WPF中嵌入WebBrowser視覺化頁面Web視覺化
- JavaScript 獲取網頁尾本程式碼內容JavaScript網頁
- 獲取網頁中的密碼和文字輸入框的內容 (轉)網頁密碼
- 001-urllib讀取網頁網頁
- python3中編碼如何獲取網頁?Python網頁
- QWebView獲取網頁原始碼WebView網頁原始碼
- 「無程式碼」高效的爬取網頁資料神器網頁
- js獲取網頁title標題程式碼例項JS網頁
- php中抓取網頁內容的程式碼PHP網頁
- 網頁黑白程式碼網頁
- js如何獲取網頁尾本程式碼的內容JS網頁
- 高效獲取網頁原始碼COM網頁原始碼
- 網頁程式碼(主頁)(初始版):網頁
- ajax讀取檔案中內容的程式碼例項
- Python中檔案讀取與儲存程式碼示例Python
- 使用CInternetSession和CHttpFile讀取網頁內容SessionHTTP網頁
- javascript實現網頁跳轉的程式碼例項JavaScript網頁
- 網頁倒數計時跳轉程式碼例項網頁
- 使用meta實現網頁跳轉程式碼例項網頁
- 網頁常用JavaScript程式碼網頁JavaScript
- 網頁JS彈出廣告程式碼,頭部,右下角,網頁中漂浮,對聯廣告程式碼等大全網頁JS
- WebBrowser頁面與WinForm互動技巧WebORM
- jQuery獲取網頁中的元素距離文件邊緣的距離程式碼例項jQuery網頁
- 轉_如何閱讀程式碼
- frank程式碼網為網頁前端人員提供建站常用的網頁js程式碼網頁前端JS
- html網頁中如何實現居中效果(程式碼分享)HTML網頁
- Python中CSV讀取和轉換Python
- IOS遍歷網頁獲取網頁中<img>標籤中的圖片urliOS網頁
- Linux網路程式碼導讀v0.2 (轉)Linux
- JavaScript頁面跳轉程式碼JavaScript
- Python網路爬蟲之爬取淘寶網頁頁面 MOOC可以執行的程式碼Python爬蟲網頁
- 網頁左右上下浮動廣告程式碼製作(轉)網頁
- 抓取網頁中的原始碼.網頁原始碼
- 獲取元素在頁面中的座標位置程式碼例項