WinForm使用WebBrowser操作HTML页面的Element
前言
在 Window Form 应用程序如果需要浏览网页时可以崁入 WebBrowser 控件,但如果需要操作崁入的 HTML 的网页元素,就需要额外的操作,以下纪录几种操作 HTML 元素的方法以及会碰到的问题。
建立 WinForm 应用程序
首先先建立一个 Window Form 应用程序,在 Form1 窗体上拉入一个 Button 与 WebBrowser 控件,如下

在 Button1 事件中使用 WebBrowser.Navigate 方法加载指定的网页,如下1.privatevoidbutton1_Click(objectsender, EventArgs e)2.{3.webBrowser1.Navigate(Application.StartupPath +"\\Page.html");4.}直接执行程序后点击「前往网页」按钮就能够看到网页已经加载 WebBrowser 控件中,如下

操作 HTML 网页中的元素
接下来如需要针对 HTML 网页上的元素进行控制时,可以透过 WebBrowser
控件提供的方法来处理,首先要在网页加载完成后才进行操作,点选 WebBrowser 控件加入 DocumentCompleted
事件,DocumentCompleted 事件是当网页文件完全加载后即会触发,就可以透过 Document、DocumentText、或
DocumentStream 属性取得网页内容,如下。01.privatevoidwebBrowser1_DocumentCompleted02.(objectsender, WebBrowserDocumentCompletedEventArgs e)03.{04.if(webBrowser1.ReadyState == WebBrowserReadyState.Complete)05.{06.ThreadPool.QueueUserWorkItem(o =>07.{08.FormWork();09.});10.}11.}12.13.privatevoidFormWork()14.{15.// 進行操作16.}透过 WebBrowser.ReadyState 属性可以知道网页使否已经加载完成,当加载完成后就使用 Thread 委派 FormWork 方法来处理网页元素的操作,相关操作方法以下列出几项。
操作文字框
1.webBrowser1.Document.GetElementById("name").SetAttribute("value","Arvin");操作下拉选单
1.HtmlElementCollection opts = webBrowser1.Document.2.GetElementById("sex").GetElementsByTagName("option");3.foreach(HtmlElement optinopts)4.{5.if(opt.GetAttribute("value") =="男")6.opt.SetAttribute("selected","selected");7.}操作单选框
1.HtmlElementCollection opts = webBrowser1.Document.2.GetElementsByTagName("input").GetElementsByName("skill");3.foreach(HtmlElement optinopts)4.{5.if(opt.GetAttribute("value") =="WebForm")6.opt.InvokeMember("click");7.}执行 JavaScript 方法 (不需写入左右括号符号)
1.webBrowser1.Document.InvokeScript("ShowInfo");取得网页内崁 iFrame 网页的内容方法
1.webBrowser1.Document.Window.Frames[0].Document以上列出几种操作网页元素的做法,不外乎就是取得元素对象再透过 SetAttribute 方法来取得或设定值,最后将几种操作方式组合后来测试自动输入窗体的功能并且希望输入窗体时能够一步一步输入,所以加入 Sleep 方法停顿一秒钟,如下
01.privatevoidFormWork()02.{03.webBrowser1.Document.GetElementById("name").SetAttribute("value","Arvin");04.Thread.Sleep(1000);05.06.webBrowser1.Document.GetElementById("phone").SetAttribute("value","0912345678");07.Thread.Sleep(1000);08.09.HtmlElementCollection opts = webBrowser1.Document.10.GetElementById("sex").GetElementsByTagName("option");11.foreach(HtmlElement optinopts)12.{13.if(opt.GetAttribute("value") =="男")14.opt.SetAttribute("selected","selected");15.}16.Thread.Sleep(1000);17.18.HtmlElementCollection opts2 = webBrowser1.Document.19.GetElementsByTagName("input").GetElementsByName("skill");20.foreach(HtmlElement optinopts2)21.{22.if(opt.GetAttribute("value") =="WebForm")23.opt.InvokeMember("click");24.}25.Thread.Sleep(1000);26.27.webBrowser1.Document.InvokeScript("ShowInfo");28.}完成后执行程序代码上就会跳出 InvalidCastException 错误,如下

其原因是因为执行绪安全的关系,无法在非主执行绪的线程下操作 UI 控件,在以上的程序代码中直接在 Thread 方法中取得 webBrowser1 控件进行操作因而导致了错误发生。
调整程序代码先使用 Control.InvokeRequired 属性来判断是否在主执行绪下执行,若不是的话则呼叫 Invoke 方法指定委派,如下。
01.privatedelegatevoidFormWorkDelegate();02.03.privatevoidFormWork()04.{05.if(webBrowser1.InvokeRequired)06.webBrowser1.Invoke(newFormWorkDelegate(FormWork));07.else08.{09.webBrowser1.Document.GetElementById("name").SetAttribute("value","Arvin");10.Thread.Sleep(1000);11.12.webBrowser1.Document.GetElementById("phone").SetAttribute("value","0912345678");13.Thread.Sleep(1000);14.15.HtmlElementCollection opts = webBrowser1.Document.16.GetElementById("sex").GetElementsByTagName("option");17.foreach(HtmlElement optinopts)18.{19.if(opt.GetAttribute("value") =="男")20.opt.SetAttribute("selected","selected");21.}22.Thread.Sleep(1000);23.24.HtmlElementCollection opts2 = webBrowser1.Document.25.GetElementsByTagName("input").GetElementsByName("skill");26.foreach(HtmlElement optinopts2)27.{28.if(opt.GetAttribute("value") =="WebForm")29.opt.InvokeMember("click");30.}31.Thread.Sleep(1000);32.33.webBrowser1.Document.InvokeScript("ShowInfo");34.}35.}在次执行后发现不会跳出错误讯息了,但是却发生另一个问题,就是当页面加载后在填入窗体值时程序会停顿一段时候才一次显示所以字段的值,这样的结果并不符合当初所要一步一步的填入窗体的需求,如下
这种问题在我此篇MSDN发问中 ThankfulHeart 大有提到,Invoke 方法是使用 UI 的线程,而如果在 UI 线程中使用了 Sleep 方法将导致 UI 画面被阻塞,因此才让画面陷入了停顿的状态。
而在 FormWork 方法中我将操作的方法都包含在 Invoke 的程序区块中,所以在此如要避免长时间的画面阻塞,应该要尽可能的切割使用到 Invoke 的区段,因此修改程序如下。
01.privatevoidFormWork()02.{03.this.Invoke(newMethodInvoker(() =>04.{05.webBrowser1.Document.GetElementById("name").SetAttribute("value","Arvin");06.}));07.Thread.Sleep(1000);08.09.this.Invoke(newMethodInvoker(() =>10.{11.webBrowser1.Document.GetElementById("phone").SetAttribute("value","0912345678");12.}));13.Thread.Sleep(1000);14.15.this.Invoke(newMethodInvoker(() =>16.{17.HtmlElementCollection opts = webBrowser1.Document.18.GetElementById("sex").GetElementsByTagName("option");19.foreach(HtmlElement optinopts)20.{21.if(opt.GetAttribute("value") =="男")22.opt.SetAttribute("selected","selected");23.}24.}));25.Thread.Sleep(1000);26.27.this.Invoke(newMethodInvoker(() =>28.{29.HtmlElementCollection opts2 = webBrowser1.Document.30.GetElementsByTagName("input").GetElementsByName("skill");31.foreach(HtmlElement optinopts2)32.{33.if(opt.GetAttribute("value") =="WebForm")34.opt.InvokeMember("click");35.}36.}));37.Thread.Sleep(1000);38.39.this.Invoke(newMethodInvoker(() =>40.{41.webBrowser1.Document.InvokeScript("ShowInfo");42.}));43.}透过切割每个动作呼叫对应的 Invoke 去执行后执行结果如下

以上就是一个简单使用 WinForm 的 WebBrowser 控件控制网页元素的方式,在此纪录一下做法。
范例程序代码
http://www.it165.net/uploadfile/2013/1017/20131017072343466.rar
延伸阅读:
WinForm使用WebBrowser操作HTML页面的Element的更多相关文章
- [WinForm] 使用 WebBrowser 操作 HTML 頁面的 Element-摘自网络
前言 在 Window Form 應用程式如果需要瀏覽網頁時可以崁入 WebBrowser 控制項,但如果需要操作崁入的 HTML 的網頁元素,就需要額外的操作,以下紀錄幾種操作 HTML 元素的方法 ...
- jquery的常用操作(操作html页面的Dom对象的元素)
一:页面加载完成时,会执行jquery的方法(不需要等待图片加载完成,只要dom结构加载完成,就执行该方法) //第一种写法: $(document).ready(function() { // 执行 ...
- 浏览器操作html页面的width和height
原文:http://www.cnblogs.com/dengshunping/archive/2009/06/15/1503803.html IE中: document.body.clientWidt ...
- [react] 什么是虚拟dom?虚拟dom比操作原生dom要快吗?虚拟dom是如何转变成真实dom并渲染到页面的?
壹 ❀ 引 虚拟DOM(Virtual DOM)在前端领域也算是老生常谈的话题了,若你了解过vue或者react一定避不开这个话题,因此虚拟DOM也算是面试中常问的一个点,那么通过本文,你将了解到如下 ...
- 高并发分布式系统中生成全局唯一(订单号)Id js返回上一页并刷新、返回上一页、自动刷新页面 父页面操作嵌套iframe子页面的HTML标签元素 .net判断System.Data.DataRow中是否包含某列 .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数
高并发分布式系统中生成全局唯一(订单号)Id 1.GUID数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么通过组合的方式,保留GUID的10个字节,用另6个字节表示GUID生成的时间(D ...
- WebBrowser之获取跳转页面的Document接口源码
问题由来是这样的,今天帮一个网友解决问题,说从VC驿站下载了一个源码,程序的功能主要是在对话框上面放置了一个WebBrowser控件,程序启动的时候默认调用这句代码: m_web.Navigate(_ ...
- 为WebBrowser的WEB页的Document注册事件的问题
原文:为WebBrowser的WEB页的Document注册事件的问题 当使用WebBrowser,并对其装载的Web页建立Document的事件后,WebBrowser里的页面元素都变得难于操作了, ...
- .Net2.0 --Winform结合WebBrowser控件和Socket老技术来实现另类Push~
原文:.Net2.0 --Winform结合WebBrowser控件和Socket老技术来实现另类Push~ 目前的企业级开发比较流行的是Web2.0技术,但是由于Web技术基于请求--响应的交互模式 ...
- C# winform调用WebBrowser经典怪问题总结
原文:C# winform调用WebBrowser经典怪问题总结 最近一直研究网页数据采集,单单采集数据,其实HtmlAgilityPack就足够了. 对HtmlAgilityPack感兴趣的可以到这 ...
随机推荐
- ajax加载表格数据
一.html代码 <style type="text/css"> .table-taskinfo table tr { border-top: 2px solid #9 ...
- Effective C++ -----条款45:运用成员函数模板接受所有兼容类型
请使用member function templates(成员函数模板)生成”可接受所有兼容类型“的函数. 如果你声明member templates 用于“泛化copy构造”或“泛化assignme ...
- C字符串和指针问题汇总
空指针和传参问题 1) 段错误.形参改为二级指针即可 void GetMemory( char *p ){ p = ( ); } void Test( void ){ char *str = NULL ...
- SpringMVC,3种不同的URL路由配置方法(这根本不是一个小问题)
转载自:http://blog.csdn.net/fansunion/article/details/41149287?utm_source=tuicool&utm_medium=referr ...
- orace 取昨天凌晨的日期
sysdate 为现在时间sysdate-1为昨天trunc(sysdate-1)为昨天凌晨0:00trunc(sysdate-1)+20/24 为昨天晚上8点select trunc(sysdate ...
- 20145213祁玮のJava课程总结
20145213のJava学习总结 每周学习笔记 1.第一周读书笔记 2.第二周读书笔记 3.第三周读书笔记 4.第四周读书笔记 5.第五周读书笔记 6.第六周读书笔记 7.第七周读书笔记 8.第八周 ...
- Android 菜单定制使用小结
GridView 添加 ArrayAdapter<Bean>, 在 gridView 的 Item 点击之后, 1.list.add(bean)/remove(bean) 2.adapte ...
- .net学习笔记----WebConfig常用配置节点介绍
一.配置文件入门 .Net提供了一种保存项目配置信息的办法,就是利用配置文件,配置文件的后缀一般是.config.在WinForm程序中配置文件一般是App.config.在Asp.net中一般默认是 ...
- 设计模式学习之适配器模式(Adapter,结构型模式)(14)
参考链接:http://www.cnblogs.com/zhili/p/AdapterPattern.html一.定义:将一个类的接口转换成客户希望的另一个接口.Adapter模式使得原本由于接口不兼 ...
- 重温WCF之发送和接收SOAP头(三)
SOAP头可以理解为一种附加信息,就是附加到消息正文的内容. 既然消息头是附加信息,那有啥用呢?你可别说,有时候还真有不少用处.举个例子,WCF的身份验证是不是很麻烦?还要颁发什么证书的(当然不是荣誉 ...