前言

鄙人才疏学浅,如果说错了,还请各位不吝赐教

1.什么是 WebBrowser

下面是已有的轮子,我想说它们是专业的

http://baike.baidu.com/view/2981935.htm?fr=aladdin

http://msdn.microsoft.com/zh-cn/library/system.windows.forms.webbrowser(v=vs.110).aspx

技巧

http://www.cnblogs.com/c51port/archive/2011/06/24/2089350.html

http://www.cnblogs.com/sufei/p/3160340.html

2.用它做什么

除了可以访问/操作网页,或者是作为数据采集一种方案,我知识有限,难想到它还能干什么,欢迎指教

很多人肯定知道,采集应该用HttpWebRequest,或者什么 WebClient之类的,那个效率要高很多

确实,HttpWebRequest效率确实高很多,因为它请求一个Web Url 获取的都是Html字符串,不会加载你采集数据基本上用不上的东西

但是如果想做简单的Web Url客户端模拟,我觉得这个还是有他的用武之地的,为什么这么说,因为它会加载js啊,然后就没有然后了.

3.怎么用

1.拖/new

2.绑定事件

3.在事件里处理动作

详细内容请在本文后下载/查看源代码

4.一点扩展,什么是闭包,C#闭包

1.什么是闭包

闭包一词经常在 Javascript 里面出现

根据名字来看可以简单解释,封闭的包,简单来说就是一个匿名函数,在这个函数里可以定义变量,外部无法访问,可以用来延长外部变量的作用时间

2.C#闭包

        /// <summary>
/// 进度条最大值
/// </summary>
public const string P_MAX = "Maximum"; /// <summary>
/// 进度条当前值
/// </summary>
public const string P_VALUE = "Value"; /// <summary>
/// 设置进度条相关参数
/// </summary>
/// <param name="p">进度条</param>
/// <param name="property"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool SetProgress(object p, string property, object value)
{
if (p != null && (p is ToolStripProgressBar || p is ProgressBar))
{
Type type = p.GetType();
type.GetProperty(property).SetValue(p, value);
return true;
}
return false;
} /// <summary>
/// 链接调用
/// 用于做返回值为boolean函数链接调用
/// </summary>
public static void R(bool b){ } /// <summary>
/// 绑定WebBrowser动作
/// </summary>
/// <param name="w">WebBrowser</param>
/// <param name="ps">任务列表</param>
/// <param name="ctrl">进度条</param>
public static void xBinding(this W w, List<PageObject> pos,object ctrl = null)
{
if (pos == null || pos.Count == 0) return; SetProgress(ctrl, P_MAX, pos.Count);
for (int i = 0, l = pos.Count; i < l; i++)
{
w.DocumentCompleted += new Func<int, PageObject, WebBrowserDocumentCompletedEventHandler>((v , o) => {
return (s , e) => R(o.DoAction(s as W) && SetProgress(ctrl, P_VALUE, v + 1));
})(i, pos[i]);
}
}
    /// <summary>
/// 页面处理对象
/// </summary>
public class PageObject
{
/// <summary>
/// 监听Url
/// </summary>
public string Url
{
get;
set;
} /// <summary>
/// 当前地址动作
/// </summary>
public Action<W> Action
{
get;
set;
} /// <summary>
/// 构造
/// </summary>
/// <param name="url"></param>
/// <param name="action"></param>
public PageObject(string url, Action<W> action)
{
this.Url = url;
this.Action = action;
} /// <summary>
/// 触发地址动作
/// 如果WebBrowser地址和需要匹配的地址一致就做当前的动作
/// </summary>
/// <param name="w"></param>
public bool DoAction(W w)
{
if (w != null && w.xIsReady() && w.xIsUrl(this.Url))
{
this.Action(w);
return true;
}
return false;
}
}

PageObject.cs

上面如果直接 += new WebBrowserDocumentCompletedEventHandler 不用闭包的话,就会出现WebBrowser每次触发DocumentCompleted事件的时候,

如果在WebBrowserDocumentCompletedEventHandler 里面引用了 i ,那么i 会一直都是 pageObjects.Count - 1

5.一点思考,怎么用

实际上说这个我比较心虚,因为我用的时候都是在DocumentCompleted处理网页里面的内容

我不知道是否有更好的方法来做网页加载完后的事情

而且最让我烦恼的是代码看上去实在不敢恭维,如果我的DocumentCompleted里面要多个页面间的事情,我就得拼命的if else

这是一件让代码很不愉快的事情,代码都不愉快了,我还怎么和它做朋友呢

然,然,然后,不管你怎么写,我反正是这么写了

        private const string U_BD = "http://www.baidu.com/";
private const string U_CB = "http://www.cnblogs.com/";
private const string U_IQ = "http://www.infoq.com/cn/";
private const string U_CD = "http://www.csdn.net/";
private const string U_MS = "http://msdn.microsoft.com/zh-CN/";
private const string U_CT = "http://www.51cto.com/";
private const string U_TB = "http://www.taobao.com"; private void frmWebBrowser_Load(object sender, EventArgs e)
{
List<PageObject> task = new List<PageObject>()
{
new PageObject(U_BD,(w)=>{ w.Navigate(U_CB); }),
new PageObject(U_CB,(w)=>{ w.Navigate(U_IQ); }),
new PageObject(U_IQ,(w)=>{ w.Navigate(U_CD); }),
new PageObject(U_CD,(w)=>{ w.Navigate(U_MS); }),
new PageObject(U_MS,(w)=>{ w.Navigate(U_CT); }),
new PageObject(U_CT,(w)=>{
w.xExecScript(@" var urlString = window.location;
function showUrl(a){
alert( urlString + ' 这个地址是最后一个任务,5秒后将进入 about:blank '+a);
setTimeout(function(){ window.location='about:blank';},5000);
}
showUrl('abc');");
}),
};
webMain.xBinding(task, progressAccessRate);
webMain.Navigate(U_BD);
}

6.结语

WebBrowser有关的内容差不多我知道的就这些了

还有一个事情我忘记说了,就是在WebBrowser里面你也许想调用下自己的javascript 函数,或者网页里面的函数

但是 WebBrowser.Document 只有一个InvokeScript,这个不是那么灵活,可能是因为我道行还不够吧

虽然示例很多时候是这样的 WebBrowser.Document.InvokeScript("alert",new object[]{ "abc" });

听说可以直接这样使用WebBrowser.Document.InvokeScript("return false");

或者这样试试

        /// <summary>
/// 执行脚本
/// 请置于WebBrowser.DocumentCompleted 事件里执行,防止调用的内容未加载完
/// </summary>
/// <param name="w">需要执行脚本的WebBrowser对象</param>
/// <param name="js">脚本</param>
public static void xExecScript(this W w, string js)
{
w.Document.InvokeScript("eval", new object[] { "(function(){ "+js+"}());" });
}

这样写后你就可以参考本文第5部分来实现自己的动作

你以为完了吗,不,还要等等,让我在啰嗦两句

网页加载完可能不是真的加载完了,也许你需要先检查 这个WebBrowser对象的ReadyState 就像这样

if(w.ReadyState == WebBrowserReadyState.Complete) {
    .... 
}

7.下载

http://files.cnblogs.com/lxmyn/MSolution.Stu.Win.WebBrowser.rar

这个是用VS2012开发的,当然我使用的是盗版,对此我深感愧疚

如果你的VS版本低那么一点点或高一点,你也许可以,通过修改.csproj文件来打开项目

如果你的低太多,你也许得自己新建一个工程,然后把代码考进去,删除掉多余的using,以及自己手写替换掉不兼容的代码

8.知识扩展

事实上,虽然WebBrowser在大多数情况下已经能够满足我们日常的要求,当然我也很希望是这样的

也许有一天,你发现,你用真实的Web浏览器和用WebBrowser访问的不一致的时候

你可以看看是否(ChromeWebBrowser.net || GeckoWebBrowser)这个是否能帮上你,虽然它是大了一点,不对,是大了很多

ChromeWebBrowser.net - Chrome

http://sourceforge.net/projects/chromewebbrowse/files/    - 下载

http://blog.csdn.net/lllllllllluoyi/article/details/28716653

GeckoWebBrowser - Firefox

http://code.google.com/p/geckofx/                                   - 下载

http://www.cnblogs.com/zhuo/archive/2010/03/19/1690237.html

【Winform 控件浅谈 】 之 WebBrowser的更多相关文章

  1. 浅谈Winform控件开发(一):使用GDI+美化基础窗口

    写在前面: 本系列随笔将作为我对于winform控件开发的心得总结,方便对一些读者在GDI+.winform等技术方面进行一个入门级的讲解,抛砖引玉. 别问为什么不用WPF,为什么不用QT.问就是懒, ...

  2. Winform控件学习笔记【第四天】——WebBrowser

    常用方法 Navigate(string urlString);//浏览urlString表示的网址 Navigate(System.Uri url);//浏览url表示的网址 Navigate(st ...

  3. WinForm控件使用文章收藏整理完成

    对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. 基础 - 常用控件 C# WinForm开发系列 - CheckBox/Button/Lab ...

  4. C#中常见的winform控件命名规范

    我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...

  5. C# WinForm控件、自定义控件整理(大全)

    转:http://www.cnblogs.com/top5/archive/2010/04/29/1724039.html 对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, ...

  6. C#中常见的winform控件命名规范 转

    我们知道Button 常常简称为btn,那么Winform中的其它控件呢,这篇文章在C#的winform控件命名规范 的基础上对一些控件的名称的简称进行了整理. 1. 标准控件 NO. 控件类型简写 ...

  7. 在WPF中使用WinForm控件方法

    1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2.      在要使用WinForm控 ...

  8. WPF 调用WinForm控件

    WPF可以使用WindowsFormsHost控件做为容器去显示WinForm控件,类似的用法网上到处都是,就是拖一个WindowsFormsHost控件winHost1到WPF页面上,让后设置win ...

  9. WinForm控件TreeView 只部分节点显示 CheckBox

    WinForm控件TreeView 只部分节点显示  CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...

随机推荐

  1. vs 点击就设置项目为默认启动项

    装好系统没注意 做项目的时候解决方案比较多 发现点击哪个项目哪个项目就成了默认启动项目 这个开始没觉出来 最后发现挺烦人的 想想难道是我装vs装的么 我于是卸载了全新安装了 还是一个吊样 无意间试了下 ...

  2. JUnit-4.11使用报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing错误

    今天尝试使用JUnit,下载了最新的JUnit版本,是4.11,结果尝试使用发现总是报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribi ...

  3. winform 获取文件夹的名称 分类: WinForm 2014-08-04 15:50 242人阅读 评论(0) 收藏

    目的:获取项目路径下所有文件夹的名称,并绑定到Combobox控件下: 显示要求:此文件夹名称和他的子文件名称的集合: Combobox控件名称:cmbFile 图示: 代码实现: //项目路径 st ...

  4. winform Label与DataGridView右对齐 分类: WinForm 2014-05-19 20:51 446人阅读 评论(0) 收藏

    实现Label与DataGridView对齐有两种方法,差别不大: 定义: Label名称:lblName DataGridView名称:dgvData 第一种: lblName.Location = ...

  5. 关于在VMware上装lFEDORA系统

    VMware虚拟机启动当中某个操作系统的时候,会出现如下提示 Cannot connect virtual device floppy0. No corresponding device is ava ...

  6. RSA算法详解及C语言实现

    RSA算法它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名:Ron Rivest, Adi Shamir 和Leonard Adleman.但 ...

  7. iOS 集合的深复制与浅复制

    概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制 ...

  8. Android(java)学习笔记201:网络图片浏览器的实现(ANR)

    1.我们在Android下,实现使用http协议进行网络通信,请求网络数据.这里是获取网络上的图片信息,让它可以显示在手机上: 但是我们这个手机连接网络是很费时间,如果我们在主线程(UI线程)中写这个 ...

  9. css考核点整理(八)-在什么情况下通过img引入图片,什么情况用背景图引入?背景属性有哪些

    在什么情况下通过img引入图片,什么情况用背景图引入?背景属性有哪些

  10. mysql 操作指令笔记

    设置区分大小写: 打开my.ini,最后加入: [mysqld] lower_case_table_names=2 (2表示区分大小写,但仅限于字段,数据库名.表名.存储过程名都是小写的) 查看方法: ...