直接访问WebBrowser控件中的HTML源码


======================================================
注:本文源代码点此下载
======================================================

直接访问webbrowser控件中的html源码

作者:

评价:

上站日期: 2002-05-22

内容说明:

来源:

html

webbrowser.oleobject.document.documentelement.innerhtml;

text

webbrowser.oleobject.document.documentelement.innertext;

********************

为了实现在自己的程序中显示html文档,我们一般采用ie(internet explorer本文中简称为ie)发行时附带的一个activex控件twebbrowser。这个控件使用和ie相同的内核,功能强大,并从delphi5开始,正式得到inprise公司的支持,取代了原来的那个thtml控件,成为delphi中显示html文档的首选控件。

但是在实际编程过程中,我发现这个控件提供的功能有很多限制,比如对html文档的浏览,只能通过指定url或文件名来实现,不能像以往使用thtml控件那样直接读写html源码。因此如果程序动态生成了一段html文本,就必须把文本内容先写到一个临时文件,然后再将此文件的文件名传递给webbrowser控件,实现显示。走这一个弯路使程序响应速度受到很大影响,而且容易遗留下一些"垃圾"(临时文件)。

---- 在考察了一些使用了webbrowser控件的程序后,我发现大部分程序,如著名国产软件foxmail,都是使用的通过临时文件传递html文档的方法;但一些国外的软件,如ms自己的outlook express则不存在这个问题,而因为其无需产生临时文件,因此对html文档的显示速度明显超过foxmail。

---- 为此,我查阅了一些相关资料,最后在网友的帮助下找到了实现直接访问webbrowser控件中的html源码的方法。在此要特别感谢白云黄鹤bbs(bbs.whnet.edu.cn)上的网友anglefalls提供线索。

---- 其实,webbrowser控件中的document对象,这个对象提供了一个ipersiststreaminit接口,通过此接口,我们可以方便地实现对html源码的读写。

---- 以下是ipersiststreaminit接口的相关定义及说明:

{ ipersiststream interface }

{$externalsym ipersiststream}

ipersiststream = interface(ipersist)

['{00000109-0000-0000-c000-000000000046}']

function isdirty: hresult; stdcall;

// 最后一次存盘后是否被修改

function load(const stm: istream): hresult; stdcall;

// 从流中载入

function save(const stm: istream;

fcleardirty: bool): hresult; stdcall;

// 保存到流

function getsizemax(out cbsize: largeint):

hresult; stdcall; // 取得保存所需空间大小

end;

{ ipersiststreaminit interface }

{$externalsym ipersiststreaminit}

ipersiststreaminit = interface(ipersiststream)

['{7fd52380-4e07-101b-ae2d-08002b2ec713}']

function initnew: hresult; stdcall; // 初始化

end;

首先来实现写,因为这是最迫切的要求:

procedure sethtml(const webbrowser:

twebbrowser; const html: string);

var

stream: istream;

hhtmltext: hglobal;

psi: ipersiststreaminit;

begin

if not assigned(webbrowser.document) then exit;

hhtmltext := globalalloc(gptr, length(html) + 1);

if 0 = hhtmltext then raiselastwin32error;

copymemory(pointer(hhtmltext),

pchar(html), length(html));

olecheck(createstreamonhglobal

(hhtmltext, true, stream));

try

olecheck(webbrowser.document.

queryinterface(ipersiststreaminit, psi));

try

olecheck(psi.initnew);

olecheck(psi.load(stream));

finally

psi := nil;

end;

finally

stream := nil;

end;

end;

---- 首先,此过程需要的两个参数,webbrowser是显示目的控件,html是需要显示的html源码;然后,先检查webbrowser.document对象是否有效,无效则退出;接着在系统全局堆里分配一块内存,将需要显示的html源码复制进去。这是因为下一步需要建立一个webbrowser控件可以读取的流。globalalloc函数的参数gptr表示需要分配一块固定的以0初始化过的内存区域,如果分配失败则返回0,则通过raiselastwin32error函数引发一个异常,提示用户;然后用createstreamon

hglobal函数建立一个基于全局堆内存块的流,第二个参数如果为true则流在释放时自动释放所占全局堆内存。如果 建立成功则此流和刚刚建立的内存块共用同一块内存区域。接着用webbrowser.document.queryinterface函数建立一个ipersiststreaminit接口。然后就可以直接使用此接口,psi.initnew初始化状态;psi.load(stream)从流中载入html源码。

---- 至此,以html参数指定的html源码就在webbrowser参数指定的控件中显示出来。

---- 值得注意的是,每个关于com接口的函数调用,也就是那些返回类型为hresult的函数,都必须以olecheck包装,因为一个不检查返回状态的com接口操作实在太危险了;此外接口的释放,虽然delphi可以在后台自动完成,但作为一个好的编程习惯,还是应该显式地手工释放,释放只需将接口设为nil即可。

---- 接着来实现html源码的读:

function gethtml(const webbrowser: twebbrowser): string;

const

bufsize = $10000;

var

size: int64;

stream: istream;

hhtmltext: hglobal;

psi: ipersiststreaminit;

begin

if not assigned(webbrowser.document) then exit;

olecheck(webbrowser.document.queryinterface (ipersiststreaminit, psi));

try

//olecheck(psi.getsizemax(size));

hhtmltext := globalalloc(gptr, bufsize);

if 0 = hhtmltext then raiselastwin32error;

olecheck(createstreamonhglobal(hhtmltext, true, stream));

try

olecheck(psi.save(stream, false));

size := strlen(pchar(hhtmltext));

setlength(result, size);

copymemory(pchar(result), pointer(hhtmltext), size);

finally

stream := nil;

end;

finally

psi := nil;

end;

end;

---- 此函数有一个参数webbrowser指定从那个控件读取html源码,返回一个字符串为此控件中的html源码。首先还是要先检查webbrowser.document对象是否有效,无效则退出;然后取得ipersiststreaminit接口;接着取得html源码的大小:本来应该使用ipersiststreaminit接口的getsizemax函数,但在我的机器上测试,这个函数范围值衡为0,无效。因此只能先定义一个足够大的缓冲区,如bufsize = $10000字节(注意此缓冲区应该足够大);然后同样地分配全局堆内存块,建立流,然后将html文本写到流中。因为此html文本在流中是以#0结尾的字符串,因此可以用size := strlen(pchar(hhtmltext))取得实际长度,用setlength(result, size);设置返回字符串长度为html源码实际长度,最后复制字符串到返回字符串中。

---- 至此,直接访问webbrowser控件中的html源码所需的两个函数全部解析完毕。

---- 不过需要注意的时,在使用这两个函数前,最好对webbrowser.document对象进行初始化。下面提供一个函数,通过显示一个空白页面实现webbrowser.document对象 初始化。

procedure showblankpage(webbrowser: twebbrowser);

var

url: olevariant;

begin

url := 'about:blank';

webbrowser.navigate2(url);

end;

---- 建议在你有webbrowser控件的form的formcreate事

件里调用此函数,初始化

webbrowser.document对象。

---- 本文程序在win nt + delphi 5 环境下调试通过


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值