分享
 
 
 

直接访问WebBrowser控件中的HTML源码 (收藏)

王朝vb·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

直接访问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 环境下调试通过

WebBrowser类和WebBrowser_V1类的区别

编号:QA002749

建立日期: 2000年3月20日 最后修改日期:2000年3月20日

所属类别:

Visual Basic - Web浏览器

xyjun:

操作系统: win98

编程工具: VB6.0

问题: 请问在vb对象浏览器中的WebBrowser类和WebBrowser_V1类的区别。

我在窗体中插入了一个WebBrowser控件,但是只有newWindow2事件,而没有newWindow事件,请问如何用newwindow事件将网页上打开的新

网页在同一窗口显示(禁止开新窗口)?以及事件newWindow2与newWindow的区别?

回答:

WebBrowser_V1是IE3的类,而IE4以后版本使用WebBrowser类。

如果你希望新打开的网页出现在同一个窗口,可以这样做:

Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)

Set ppDisp = WebBrowser1.Object

End Sub

事件NewWindow2与newWindow的区别有较大区别,使用事件NewWindow你可以知道点击的链接是什么,而使用事件NewWindow2无法知道。而

NewWindow只有在用户选择“在新窗口打开链接”时才会激发,而NewWindow2除了在此时激发外,当网页使用window.open打开新窗口时也激发

。上面的工作也可以使用NewWindow实现:

Dim WithEvents Web_V1 As SHDocVwCtl.WebBrowser_V1

Private Sub Form_Load()

Set Web_V1 = WebBrowser1.Object

WebBrowser1.Navigate2 "http://askpro.yeah.net"

End Sub

Private Sub Web_V1_NewWindow(ByVal URL As String, _

ByVal Flags As Long, _

ByVal TargetFrameName As String, _

PostData As Variant, _

ByVal Headers As String, _

Processed As Boolean)

Processed = True

WebBrowser1.Navigate URL

End Sub

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有