800分求TWebBrowser问题(300分)

  • 主题发起人 主题发起人 yellowyellow
  • 开始时间 开始时间
转帖
1、基本操作
1.1、激活
var doc,url:Olevariant ;
begin
url:='about:blank' ;//或者一个有实际意义的url
WebBrowser1.Navigate2(url);//这样就激活了!
end;
1.2、写HTML代码
var doc:Olevariant ;
s:string;
begin
doc:=WebBrowser1.Document;
doc.clear;//清楚缘由内容,以便写新内容
doc.write('<html>');
//其它代码
doc.write('</html>');
doc.close;//这样就生效了!
end;
1.3、获得HTML文本
var doc:Olevariant ;
s:string;
begin
doc:=WebBrowser1.Document;
s:=doc.documentElement.outerHTML;//s里就是HTML文本了
//处理s就行了
end;
2、中级操作
2.1、获得其中HTML元素的值
var doc:olevariant;
s:string;
begin
doc:=WebBrowser1.Document;
s:=doc.all.btn.value;
end;
2.2、改写其中HTML元素的值
var doc:olevariant;
begin
doc:=WebBrowser1.Document;
doc.all.btn.value:='123123';
end;
3、高级操作
3.1、触发其中HTML元素的事件
var doc:olevariant;
begin
doc:=WebBrowser1.Document;
doc.all.btn.onclick;
end;
3.2、让其中的元素执行webbrowser之外的delphi代码
本来,这有很复杂的解决办法,但那部分属于ATL的知识比较难掌握,因此绕了一下:
让那些需要执行delphi的HTML元素,调用一个函数叫做triggerExEvent,参数是HTML元素的名称,然后是若干参数。
triggerExEvent是javascript函数,有不确定个参数,但第一个肯定是表示元素的名称。 triggerExEvent将参数组成字符串,然后前面冠以&quot;#OnTriggerExEvent:&quot;,作为url,然后导航。
在webbrowser的onNavigator2事件里,判断url中是否包含&quot;#OnTriggerExEvent:&quot;,如果包含怎作如下处理:
a、cancel这次导航;b、将&quot;#OnTriggerExEvent:&quot;之后的信息截取,作为参数传递给webbrowser的新增一个事件OnTriggerExEvent事件,其参数有两个:1、控件名称;2、一个字符串参数。
这样,用户可以在OnTriggerExEvent事件里处理HTML的点击等事件了
例如,我为webbrowser派生新类,叫做webbrowserEx,它有一个事件叫做OnTriggerExEvent
有个js文件包含这样的函数:
function triggerExEvent(cmpnt_id,event_nm,optionstr)
{url='#triggerExEvent:id=';
url=url+cmpnt_id+';eventnm='+event_nm;
if(optionstr) url=url+';params=optionstr';
location=url;}
在HTML文本里可以这样写:
<input type=&quot;button&quot; name=&quot;Submit&quot; value=&quot;按钮&quot; onClick=&quot;triggerExEvent('Submit','click',null);&quot;>
这样,点击网页里的按钮时,会触发delphi写的代码,这些代码根据传递过来的参数,再进行调用其它合适的事件,也可以让webbrowserEx自动寻找合适的事件来触发,只有寻找不到时才……
 
http://www.cnblogs.com/duhai_lee/archive/2006/02/07/326434.html
 
楼主的问题初看简单,实际上很难!试了很多方法都不行!
 
问题: 用TWebBrowser如何取到带框架(Frame)网页里面的代码?即某框架里的代码? ( 积分: 100 )
分类: Internet/TCPIP

来自: wenewboy, 时间: 2005-09-09 11:20:00, ID: 3198046
procedure GetHtmlDoc(var theList: TStringList);
var
all:IHTMLElementcollection;
doc:IHTMLDocument2;
item:OleVariant;
begin
doc := Browser.document as ihtmldocument2;
all:=doc.all;
item:=all.item(0,varEmpty);
//item.innerhtml是源文件的title到body
//item.outerhtml是全文
theList.Add( item.innerhtml );
end;

按上面的方法我只能取到框架(frame)的代码,如下网站,
很多网站都用了框架,就不能取到有用的数据了,
请问能不能取到框架里面的网页源代码?

<HEAD><TITLE>Welcome </TITLE>
<META http-equiv=Content-Type content=&quot;text/html; charset=big5&quot;></HEAD>
<FRAMESET border=0 frameSpacing=0 rows=*,0 frameBorder=NO>
<FRAME name=SI2_mem_index src=&quot;app/member/&quot;><FRAME name=SI2_func c=&quot;../ok.html&quot; noResize scrolling=no><FRAME src=&quot;*&quot;></FRAMESET>

来自: chenybin, 时间: 2005-09-09 12:26:59, ID: 3198125
doc.Frames[xxxxx]可以获得那个框架,获得网页代码的的代码等会有很多人来给你写的[:D][:D]

来自: iamy, 时间: 2005-09-09 11:45:34, ID: 3198136
http://www.2ccc.com/article.asp?articleid=2182
里面有你想要的代码

来自: 无泪, 时间: 2005-09-09 11:50:36, ID: 3198151
直接访问WebBrowser控件中的HTML源码



---- 为了实现在自己的程序中显示HTML文档,我们一般采用IE(Internet Explorer本文中简称为IE)发行时附带的一个ActiveX控件TWebBrowser。这个控件使用和IE相同的内核,功能强大,并从Delphi5开始,正式得到Inprise公司的支持,取代了原来的那个THTML控件,成为Delphi中显示HTML文档的首选控件。

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

---- 在考察了一些使用了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函数引发一个异常,提示用户;然后用CreateStreamOnHGlobal函数建立一个基于全局堆内存块的流,第二个参数如果为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 环境下调试通过

来自: iamy, 时间: 2005-09-09 11:53:44, ID: 3198167
procedure Tform_chat.writemsgall(msg: string);
var
D: IHTMLDocument2;
OleI: olevariant;
OleWin: olevariant;
aWindow: IHTMLWindow2;
Form : IHTMLFormElement;
begin
try
d:=msgall.document as IHTMLDocument2;
//d:=d.frames.item('0') as HTMLFrameElement);
OleI:=1;
OleWin:=D.Frames.Item(OleI);//********************通过这行取得frame
IUnknown(OleWin).QueryInterface(IID_IHTMLWindow2, aWindow);
d:=awindow.document;
//showmessage(awindow.document.body.innerHTML);
Form := awindow.document.Forms.item('f',0) as IHTMLFormElement;
(form.item('msg',0) as IHTMLElement).setAttribute('value',msg,0);
(form.item('sc',0) as IHTMLElement).setAttribute('checked',ac_scrmsg.Checked,0);
(form.item('b',0) as IHTMLElement).click;
d:=nil;
except
messagebox(handle,'无法正常写入消息!请检查Internet Explorer是否脱机工作!','错误',mb_ok+mb_iconerror);
end;
end;

来自: CathyEagle, 时间: 2005-09-09 20:09:07, ID: 3199190
http://blog.csdn.net/cathyeagle/archive/2004/09/30/121540.aspx

来自: wenewboy, 时间: 2005-09-14 18:48:09, ID: 3205618
多人接受答案了。

得分大富翁: CathyEagle-20,chenybin-20,iamy-20,无泪-40,
 
楼上的讲的都是些正常情况下网页源码的取出方法,而没有针对yellowyellow提出的具体网站:http://aro999.com/,这个网页的源码是做过技术处理的,用上面的方法都无法完全读出源代码. 还是用别的方法试试吧.
 
frames:=wb.OleObject.document.frames;
for i:=0 to frames.length do
memo1.lines.Add(frames.document.body.innerHTML);

800分全给我啊
 
后退
顶部