[转]WebBrowser页面与WinForm交互技巧

正文转自:http://www.cnblogs.com/zjj2816/archive/2006/12/26/603659.html

1、前言

对此广大初次接触Web端即时通信技术的人的话,WebSocket是个很新的概念,但毋庸置疑它是时下Web端即时通信技术中最抢手的显要词。随便点开一篇小说,只要说打算开发Web端即时通讯相关的的使用,老驾驶员们推荐的无一例外都以WebSocket。

那正是说好了,作者驾驭应该用WebSocket,但针对知其然知其所以然的码农习惯,小编还是必要掌握下边这么些标题:

1)Socket 和 WebSocket 有怎么着分化和交换?

2)WebSocket 和 HTML5 是什么样关联?

3)必须在浏览器中才能选取 WebSocket 吗?

4)WebSocket 能和 Socket 一样传输 raw 数据么?

5)WebSocket 和 Socket 相比较会多消耗流量么?

而是,近期网前一周全介绍那二种协议的汉语文章并不多,可能说不够周密。小编一筹莫展找到一篇文章能一蹴而就地点的富不通常。因而,笔者写了本文,把找到的
Socket 和 WebSocket 的有关材质做三个梳理,以便于精通。

正文并不可能一向完整回答下边提议的多少个难点,但读完本文,要精通地点的这多个难题,是很简单的事。由于能力有限,本文不容许非常长。而且,技术细节并非全数人都乐于仔细询问。但本文包蕴了汪洋的外部链接,跟随这几个链接,可以找到丰富多的底细,满足你/小编的求知欲。Are
you ready?

上学调换:


即时报纸公布支出调换群:320837163[推荐]


移动端IM开发入门作品:《新手入门一篇就够:从零付出活动端IM

(本文同步发表于:http://www.52im.net/thread-1273-1-1.html

初稿如下:

贰 、体系小说

本文是不可胜计小说中的第六篇,本体系小说的提纲之类:

WebSocket详解(一):开头认识WebSocket技术

WebSocket详解(二):技术原理、代码演示和使用案例

WebSocket详解(三):深切WebSocket通讯协议细节

WebSocket详解(四):刨根问底HTTP与WebSocket的关联(上篇)

WebSocket详解(五):刨根问底HTTP与WebSocket的涉及(下篇)

WebSocket详解(六):刨根问底WebSocket与Socket的涉嫌》(本文)

《WebSocket详解(七):WebSocket协议与Socket.io开源工程》

 

叁 、更加多材质

Web端即时通信新手入门贴:

新手入门贴:详解Web端即时通信技术的法则

Web端即时通信技术盘点请参见:

Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

关于Ajax短轮询:

找那上头的素材没什么意思,除非忽悠客户,不然请考虑任何3种方案即可。

至于Comet技术�的详实介绍请参见:

Comet技术详解:基于HTTP长连接的Web端实时通讯技术

WEB端即时通信:HTTP长连接、长轮询(long
polling)详解

WEB端即时通信:不用WebSocket也如出一辙能化解消息的即时性

开源Comet服务器iComet:帮忙百万涌出的Web端即时通信�方案

有关WebSocket的事无巨细介绍请参见:

新手急忙入门:WebSocket简明教程

WebSocket详解(一):初叶认识WebSocket技术

WebSocket详解(二):技术原理、代码演示和平运动用案例

WebSocket详解(三):深远WebSocket通讯协议细节

Socket.IO介绍:援助WebSocket、用于WEB端的即时通信的框架

socket.io和websocket
之间是怎么着关系?有啥样分别?

关于SSE的事无巨细介绍文章请参见:

SSE技术详解:一种崭新的HTML5服务器推送事件技术

越来越多WEB端即时通讯小说请见:

http://www.52im.net/forum.php?mod=collection&action=view&ctid=15

话说有了WebBrowser类,终于不用本人手动封装SHDocVw的AxWebBrowser这一个ActiveX控件了。那一个类如果唯有作为2个和IE一模一样浏览器,那就太平淡了(还不如直接用IE呢)。那么,无论大家是想做3个“定制版IE”,依然盼望选拔HTML来做用户界面(指WinApp而非WebApp。许多单机软件,包含Windows的帮助支持中央,都以HTML做的),都必不可少Windows
Form和蕴含在WebBrowser中的Web页面包车型大巴互相。本文将经过多少个实际的例子,开首介绍一下WinForm和WebBrowser所包罗的Web页面之间的竞相。

④ 、技术比较

慎选了 WebSocket
技术之后,不可制止的,小编要将它和任何协商以及技术做一下比较。最广大的,正是须要相比较WebSocket 与 HTTP、Socket
技术的异议。本类别小说中《WebSocket详解(四):刨根问底HTTP与WebSocket的涉嫌(上篇)》、《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》两篇详细座谈了WebSocket和HTTP的关系,那么本篇将只谈谈WebSocket和Socket的话题。

WebSocket 是为了知足基于 Web 的增加的实时通讯需要而产生的。在观念的
Web 中,要达成实时通讯(比如网页的QQ,聊天系统等),通用的办法是接纳HTTP
协议持续发送请求(根据过去的技术能力一般是行使轮询、Comet技术化解)。

HTTP协议是非持久化的,单向的互联网协议,在确立连接后只同意浏览器向服务器发出请求后,服务器才能重回相应的数码。当须要即时通信时,通过轮询在一定的时光距离(如1秒),由浏览器向服务器发送Request请求,然后将最新的多寡重临给浏览器。那样的艺术最醒指标瑕疵正是内需持续的发送请求,而且平时HTTP
request的Header是老大长的,为了传输3个相当小的数据
须求交给巨大的代价,是很不合算的,占用了很多的宽带。那种艺术即浪费带宽(HTTP
HEAD 是相比大的),又开销服务器 CPU 占用(没有音信也要经受请求)。

▲ 轮询和WebSocket技术在互联网延迟上的自己检查自纠(本图来自:websocket.org)

而是用 WebSocket 技术,则会大幅降低地点提到的开支,如下图所示。

▲ 轮询和WebSocket技术在数据流量消耗上的对照(本图来自:websocket.org)

有关更详尽的叙述,尹立的这篇小说讲得极度好:《WebSocket(2)–为啥引入WebSocket商谈》。

那就是说,WebSocket 到底和 Socket 又有如何联系?那就要讲到 OSI 模型和 TCP/IP
协议族。

上边的代码借使你已经创建了1个Windows
Form,上边有一个WebBrowser名为“webBrowser”。

5、OSI 模型与 TCP/IP

以下是维基百科中有关OSI
模型的证实:

开放式系统互联通讯参考模型(日语:Open System Interconnection
Reference Model,ISO/IEC 7498-1),简称为OSI模型(OSI
model),一种概念模型,由国际标准化组织(ISO)提议,二个意欲使各样总结机在世界范围内互连为互连网的正经框架。

而 TCP/IP 协议得以看做是对 OSI
模型的一种简化(以下内容来自维基百科):

它将软件通讯进程抽象化为四个抽象层,采纳协议堆叠的办法,分别实作出差别通讯协议。协议套组下的各样协商,依其效用各异,被分别归属到那多少个阶层之中7,常被视为是简化的七层OSI模型。

那边有一张图详细介绍了 TCP/IP 协议族中的相继协议在 OSI模型
中的分布,一图胜千言(此图高清版:点此下载):

TCP/IP 协和式飞机和 OSI
模型的情节,在互连网上有很多。笔者尚未供给再度介绍它们。在那边,大家只必要领会,HTTP、WebSocket
等协议都以处在 OSI 模型的最高层: 应用层 。而 IP
协议工作在网络层(第三层),TCP 探究工作在传输层(第五层)。

至于 OSI
模型的一一层次都有怎么样系统和它们对应,那里有篇很好的篇章能够满足我们的求知欲:OSI七层模型详解

Study Case 1:用WinForm的伊芙nt Handler响应Web页面包车型大巴事件

6、WebSocket 与 TCP

从地点的图中得以看到,HTTP、WebSocket 等应用层协议,都是依据 TCP
协商来传输数据的,我们得以把这几个高档协议明白成对 TCP 的卷入。

既然我们都利用 TCP 协议,那么大家的延续和断开,都要遵照TCP
协议中的二回握手和6遍握手
,只是在接连之后发送的剧情分歧,只怕是断开的年华不一。

更详尽内容可观察:wireshark抓包图解
TCP二遍握手/9次挥手详解
》。

对此 WebSocket 来说,它必须借助 HTTP 协议举办三次握手
,握手成功后,数据就直接从 TCP 通道传输,与 HTTP
非亲非故了(具体可见文章《WebSocket详解(五):刨根问底HTTP与WebSocket的涉及(下篇)》)。

现行反革命有诸如此类二个Windows
Application,它的界面上唯有贰个WebBrowser,展现2个本地的HTML文件作为界面。现在的标题是,全部逻辑都得以置身HTML文件里,唯独“关闭”按钮蒙受了困难——平常,Web页面是一直不章程直接控制浏览器的,更毫不说得了这些WinForm程序了。

⑦ 、再来八卦一下WebSocket的缘由

是因为时代久远,计算机方面许多事情也搞不了那么明亮。但WebSocket是多少个很新的东西,能够让我们见到它是怎么样成为今后我们来看的那几个样子的。

不过,在.Net 2.0个中,“由Windows Form响应Web页面包车型大巴事件”已经成为了现实。

7.1 WHATWG(Web Hypertext Application Technology Working Group)

关于HTML5的传说很多少人都是驾驭的,w3c遗弃了HTML,然后有一群人(也有正是这几个人供职的营业所,然而官方的文书档案上是说的私人住房)创建了WHATWG组织来推进HTML语言的继承开拓进取,同时,他们还发展了不少关于Web的技术标准,这几个规范不断地被官方所收受。WebSocket就属于WHATWG发表的Web
Application的一部分(即HTML5)的产物。

在.Net
2.0中,整个HTML文书档案以及其蕴藉的一一HTML成分,都和1个个HtmlDocument、HtmlElement之类的.Net对象对应。因而一旦找到那些“关闭”按钮对应的HtmlElement对象,为其click事件添加伊芙nt
Handler即可。

7.2 为何会有WebSocket

约莫在08年的时候,WG的工程师在切磋互连网环境中供给一种全双工的连天格局,刚初叶一直号称「TCPConnection」,并钻探了那种协议必要扶助的效益,大概已经和大家明天看看的WebSocket大约了。他们觉得基于现有的HTTP之上的一些技艺(如长轮询、Comet)并满意不断那种须要,有要求定义二个全新的商业事务。

倘诺HTML源代码如下:

7.3 名称的来头

在不少的关于HTML5只怕WebSocket的文书档案中,都能来看三个名字,Hixie(Ian希克斯on),他是WHATWG组织的发言人,曾任职于Netscape、Opera、谷歌,看办事的店铺就清楚此人的背景了。

▲ hixie

08年四月三十五日,一群WHATWG的工程师在研商一些技能难点,三个工程师提到说「大家事先商量的要命东西,不要叫TCPConnection
了,照旧起分其余名字吧
」,接着几个名字被提及,DuplexConnection,TCPSocket,SocketConnection
,2个叫mcarter(迈克尔 Carter)的工程师说她立刻要写一篇关于Comet的篇章,假如得以明确那么些称呼,想在小说中引用这么些名字。

Socket一贯以来都被人用来表示网络中3个连连的双面,考虑到怎么让工程师更容易接受,后来Hixie说了一句「作者看WebSocket那几个名字就很合乎嘛(Hixie
briefly pops back online to record that “WebSocket” would probably be a
good new name for the TCPConnection
object)」,大家都未曾异议,紧接着mcarter在Comet
Daily中宣布了稿子《Independence Day: HTML5 WebSocket Liberates Comet
From
Hacks
》,后来随着各大浏览器对WebSocket的支撑,它变成了事实上的专业,IETF也沿用了那么些名字。

下边是在WHATWG文书档案中对WebSocket接口的定义:

enum BinaryType {“blob”,”arraybuffer”};

[Constructor(USVString url, optional (DOMString or sequence)
protocols = []), Exposed=(Window,Worker)]

interface WebSocket : EventTarget {

readonly attribute USVString url;

// ready state

const unsigned short CONNECTING = 0;

const unsigned short OPEN = 1;

const unsigned short CLOSING = 2;

const unsigned short CLOSED = 3;

readonly attribute unsigned short readyState;

readonly attribute unsigned long long bufferedAmount;

// networking

attribute EventHandler onopen;

attribute EventHandler onerror;

attribute EventHandler onclose;

readonly attribute DOMString extensions;

readonly attribute DOMString protocol;

void close([Clamp] optional unsigned short code, optional USVString
reason);

// messaging

attribute EventHandler onmessage;

attribute BinaryType binaryType;

void send(USVString data);

void send(Blob data);

void send(ArrayBuffer data);

void send(ArrayBufferView data);

};

<html>
<body>
<input type=”button” id=”btnClose” value=”关闭” />
</body>
</html>

⑧ 、再来看看Socket

Socket能够有诸多意思,和IT较相关的本意大约是指在端到端的八个一而再中,那八个端叫做Socket。对于IT从业者来说,它往往指的是TCP/IP网络环境中的五个连接端,大部分的API提供者(如操作系统,JDK)往往会提供遵照那种概念的接口,所以对于开发者来说也频仍是在说一种编制程序概念。同时,操作系统中经过间通讯也有Socket的概念,但以此Socket就不是基于互连网传输层的商谈了。

那么找出该按钮并为之添加伊夫nt Handler的代码如下:

8.1 Unix中的Socket

操作系统中也有应用到Socket那几个概念用来拓展进度间通讯,它和一般性说的基于TCP/IP的Socket概念十二分相似,代表了在操作系统中传输数据的两方,只是它不再基于网络协议,而是操作系统本身的文件系统。

 

8.2 互联网中的Socket

普通所说的Socket
API,是指操作系统中(也大概不是操作系统)提供的对于传输层(TCP/UDP)抽象的接口。现行反革命的Socket
API差不离都以遵照了BSD
Socket规范(包涵Windows)。那里称规范其实不太标准,规范其实是POSIX,但BSD
Unix中对于Socket的贯彻被广为使用,所以变成了事实上的正规化。假诺你要动用HTTP来营造服务,那么就不必要关爱Socket,如若您想依据TCP/IP来创设服务,那么Socket或然正是您会触发到的API。

▲ 在TCP/IP网络中HTTP的位置

从上海教室中能够看到,HTTP是依据传输层的TCP协议的,而Socket
API也是,所以只是从使用上说,能够认为Socket和HTTP类似(但八个是作品的网络协议,二个是直接沿用的一种编程概念),是对此传输层协议的另一种直接选择,因为依照陈设,互联网对用户的接口都应该在应用层。

HtmlDocument htmlDoc = webBrowser.Document;
HtmlElement btnElement = htmlDoc.All[“btnClose”];
if (btnElement != null)
{
    btnElement.click += new HtmlElementEventHandler(HtmlBtnClose_Click);
}

8.3 Socket名称的来头

和众多任何Internet上的事物一样,Socket这几个名号来自于名牌的A奥迪Q5PANET(Advanced
Research Projects
Agency),早期ARAV4PANET中的Socket指的是一个源如故指标地址——大概正是前天大家所说的IP地址和端口号。最早的时候三个Socket指的是2个四十三个人的数字(大切诺基FC33中证实了此用法,但在WranglerFC36中并从未显著性地说利用肆11人数字来标识3个地方),在那之中前32为指向的地址(socket
number,大概相当于IP),后8个人为发送数据的源(link,大约相当于端口号)。对他们的叫法有那2个的本子,那里列举的并不严格。

其中HtmlBtnClose_Click是按下Web按钮时的伊夫nt Handler。

8.4 端口号的野史

乘势A索罗德PANET的前进,后来(中华VFC433,Socket Number List)socket
number被显眼地定义为2个四十一人的数字,在那之中后8人被用来制订某些特定的采用使用(比如1是Telnet)。那六人数有不少名字:link、socket
name、AEN(another eight
number,看到这几个名字小编也是醉了),工程师逗逼起来也是挺拼的。

后来在Internet的正儿八经制定中,才真的的用起了port
number那个词。至于怎么端口号是十六位的,笔者想或然有多少个原因,一是对此当下的工程师来说,要是每一个端口号来标识三个程序,655叁拾八个端口号也大半够用了。二或者是为着对齐吗,_!!。

相当的粗略吗?那么稍稍高级一点的——大家都知晓五个HTML成分恐怕有成千成万形形色色的风浪,而HtmlElement这么些类只交给最常用、共通的多少个。那么,如何响应其他事件呢?那也很简单,只需求调用HtmlElement的Attach伊芙ntHandler就足以了:

8.5 Socket原本的意思

在上边提到的历史中使用到的Socket,包蕴TCP文书档案中应用到的Socket,其实指的是网络传输中的一端,是一个虚拟化的概念。

btnElement.AttachEventHandler(“onclick”, new EventHandler(HtmlBtnClose_Click)); 
//这一句等价于上边的btnElement.click += new HtmlElement伊夫ntHandler(HtmlBtnClose_Click); 

9、Socket 与 WebSocket 的关系

正如上节所述:Socket 其实并不是八个商业事务,它工作在 OSI
模型会话层(第⑤层),是为着便利我们平素采取更底层协议(一般是TCPUDP)而存在的八个抽象层。

最早的一套 Socket API 是Berkeley
sockets
,接纳C 语言完毕。它是 Socket 的事实标准,POSIX sockets
是遵照它营造的,多样编制程序语言都遵循那套 API,在 JAVA、Python
中都能见到那套 API 的黑影。

下边摘录一段更易于明白的文字(来自
http和socket之长连接和短连接差别):

Socket是应用层与TCP/IP协议族通讯的中等软件抽象层,它是一组接口。在设计方式中,Socket其实便是一个伪装方式,它把复杂的TCP/IP协议族隐藏在Socket接口后边,对用户来说,一组大约的接口便是全体,让Socket去组织数据,以合乎钦点的协议。

长机 A 的应用程序要能和主机 B 的应用程序通讯,必须透过 Socket
建立连接,而树立 Socket 连接必须要求底层 TCP/IP 协议来树立 TCP
连接。建立 TCP 连接须求底层 IP
协议来寻址互连网中的主机。我们知晓网络层使用的 IP 协议能够帮忙大家根据IP
地址来找到对象主机,然则一台主机上或者运维着四个应用程序,怎么样才能与钦命的应用程序通讯就要通过
TCP 或 UPD 的地址也正是端口号来钦赐。那样就足以经过三个 Socket
实例唯一象征一个主机上的3个应用程序的通讯链路了。

而 WebSocket
则差异,它是3个完好无缺的应用层协议,包涵一套标准的
API

因此,从利用上来说,WebSocket 更易用,而 Socket 更灵活。

对于其余事件,把”onclick”换到该事件的名字就可以了。例如:

⑨ 、最终提一下 HTML5 与 WebSocket 的关系

WebSocket
API
HTML5行业内部的一有的,
但那并不意味着 WebSocket 一定要用在 HTML
中,只怕只还好依据浏览器的应用程序中运用。

其实,许多语言、框架和服务器都提供了 WebSocket 协助,例如:

1)基于 C
libwebsocket.org

2)基于 Node.js
Socket.io

3)基于 Python
ws4py

4)基于 C++
WebSocket++

5)Apache 对 WebSocket 的支持:Apache Module
mod_proxy_wstunnel

6)Nginx 对 WebSockets 的支持:NGINX as a WebSockets
Proxy
NGINX
Announces Support for WebSocket
Protocol
WebSocket
proxying

7)lighttpd 对 WebSocket
的支持:mod_websocket

formElement.AttachEventHandler(“onsubmit”, new EventHandler(HtmlForm_Submit)); 

附录:别的Web端即时通信技术小说

新手入门贴:史上最全Web端即时通信技术原理详解

Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE

SSE技术详解:一种崭新的HTML5服务器推送事件技术

Comet技术详解:基于HTTP长连接的Web端实时通信技术

新手快捷入门:WebSocket简明教程

socket.io完成音讯推送的一点执行及思路

LinkedIn的Web端即时通信实践:达成单机几八万条长连接

Web端即时通信技术的上进与WebSocket、Socket.io的技艺实施

Web端即时通信安全:跨站点WebSocket威逼漏洞详解(含示例代码)

开源框架Pomelo实践:搭建Web端高品质分布式IM聊天服务器

运用WebSocket和SSE技术完毕Web端音信推送

详解Web端通信情势的变异:从Ajax、JSONP 到
SSE、Websocket

MobileIMSDK-Web的网络层框架为什么选取的是Socket.io而不是Netty?

>>越来越多同类小说……

(本文同步公布于:http://www.52im.net/thread-1273-1-1.html

**Study Case
2:表单(form)的机动填写和付出
**

要使我们的WebBrowser具有电动填表、甚至机关提交的效用,并不困难。

如若有二个最简单易行的登录页面,输入用户名密码,点“登录”按钮即可登录。已知用户名输入框的id(或Name,下同)是username,密码输入框的id是password,“登录”按钮的id是submitbutton,那么大家只须要在webBrowser的DocumentCompleted事件中使用上边包车型客车代码即可:

HtmlElement btnSubmit = webBrowser.Document.All[“submitbutton”];
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方法:

HtmlElement formLogin = webBrowser.Document.Forms[“loginForm”]; 
//…… 
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;)

 

    public partial class SearchDemo : Form
    {
        // 建立1个搜寻用的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中的内容。代码片断如下:

    public partial class HilightDemo : Form
    {
        // 定义高亮显示效果的竹签。
        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,然后遍历各类节点,在在那之中搜索关键字并开始展览对应替换处理即可。

    public partial class HilightDemo : Form
    {
        //……

        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:

<b>Hel</b>lo World!

先不管小编出于怎么着指标让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:

function DoAdd(a, b) {
    return a + b;
}

那么,大家要在WinForm调用它,只需如下代码即可:

object oSum = webBrowser.Document.InvokeScript(“DoAdd”, new object[] { 1, 2 });
int sum = Convert.ToInt32(oSum);

其次,假使我们想进行一段Web页面中原本没有的脚本,该怎么办啊?这一次.Net的类没有提供,看来还要依靠COM了。IHTMLWindow2能够将随机的字符串作为脚本代码来执行。

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(‘网页的总计结果:\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”);

发表评论

电子邮件地址不会被公开。 必填项已用*标注