Skip to content

Instantly share code, notes, and snippets.

@melice
Created April 8, 2012 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melice/2337542 to your computer and use it in GitHub Desktop.
Save melice/2337542 to your computer and use it in GitHub Desktop.
(Delphi)操作Webbrowser
如何获取 WebBrowser 对象模型的一个 HTML 框架
概要
可以使用此文章详细标准技术 WebBrowser 控件主机来访问 WebBrowser 对象模型的控件中的 HTML 页中框架窗口。 此对象模型提供对框架窗口通过 HTML 对象模型不公开额外功能。
更多信息
以下代码演示如何访问 WebBrowser 对象模型是一个 HTML 页中框架要刷新的各个框架内容。
最重要的代码使用的 HTML 文档对象 IOleContainer::EnumObjects 方法来枚举页上嵌入。 每个这些嵌入表示页上控件。 此代码通过查询每个控件对象的 IWebBrowser 2, 可以确定控件是否 sub-frame。 和 IWebBrowser 2 代表 WebBrowser 对象模型 ; 如果为该接口, QueryInterface 成功结果是对 WebBrowser 对象模型。 // Get the IDispatch of the document
LPDISPATCH lpDisp = NULL;
lpDisp = m_webBrowser.GetDocument();
if (lpDisp)
{
IOleContainer* pContainer;
// Get the container
HRESULT hr = lpDisp->QueryInterface(IID_IOleContainer,
(void**)&pContainer);
lpDisp->Release();
if (FAILED(hr))
return hr;
IEnumUnknown* pEnumerator;
// Get an enumerator for the frames
hr = pContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator);
pContainer->Release();
if (FAILED(hr))
return hr;
IUnknown* pUnk;
ULONG uFetched;
// Enumerate and refresh all the frames
for (UINT i = 0; S_OK == pEnumerator->Next(1, &pUnk, &uFetched); i++)
{
IWebBrowser2* pBrowser;
hr = pUnk->QueryInterface(IID_IWebBrowser2, (void**)&pBrowser);
pUnk->Release();
if (SUCCEEDED(hr))
{
// Refresh the frame
pBrowser->Refresh();
pBrowser->Release();
}
}
pEnumerator->Release();
}
注意 HTML 页中承载 ActiveX 控件可使用此技术以类似方式。 一般, ActiveX 控件访问 unsafe WebBrowser 对象模型是不安全对于脚本并应实现 IObjectSafety 接口相应的安全的安全。
1.获得网页中变量值
htm中<script> var currID=123</script>
程序中可以这么调用 id := Form1.WebBrowser1.OleObject.Document.script.currID
值得说明的是,变量可以是javascript定义的,也可以是vbscript定义的,如果Webbrowser1中找不到该变量,调用会触发一个异常事件,即变量currID不存在
2.执行网页中的函数
tmp := 'currID = getNextID(currID)'+#13#10;
Form1.WebBrowser1.OleObject.Document.parentWindow.execScript(tmp,'JavaScript');
调用函数的方法就是execScript接口,同样,如果函数不存在,或者运行错误也会触发脚本错误异常
3.设置网页背景
背景图片 WebBrowser1.OleObject.Document.body.background := 'http://seelearn.com/bg.gif
' 背景颜色 WebBrowser1.OleObject.Document.body.bgcolor := '#eeeeee'
4.调用网页中已知对象
src := WebBrowser1.OleObject.Document.getElementByID('img1').src 该方法其实就是javascript中的 getElementByID
5.获取页面中所有的frame
使用DHTML。
frames:=wb.OleObject.document.frames;
for i:=0 to frames.length do
memo1.lines.Add(frames[i].document.body.innerHTML);
6.BorderStyle=bsNone后Webbrowser会被重新初始化
这是一个让人很意外的一个问题,Delphi在窗口控件的控制方面做得非常好,很少出现这种BUG
根据分析,出现这个现象有很多情况 改变FormStyle也会出现 ; 如果 webbrowser.parent
由panel1改到panel2.也会导致webbrowser重新初始化。
7.直接向Webbrowser中写入html代码,不需要Navigate到实际存在的文件
var
StrStream:TStringStream;
SetNoteStr: string; begin SetNoteStr :='<body bgcolor=222222 align=center><br><p align=center><font size=+2 color=#FFFFFF>扬帆博客 http://wesohon.com</font></p>';
SetNoteStr :=SetNoteStr+'<br><p align=center><font size=+2 color=#FFFFFF>点击左边按钮可查看对应图片</font></p>';
StrStream:=TStringStream.Create(SetNoteStr);
WebBrowser1.Navigate('about:blank');
try
StrStream.Position:=0;
( WebBrowser1.Document as IPersistStreamInit).Load(TStreamadapter.Create(StrStream));
finally
StrStream.Free;
end;
8.前进,后退,刷新
self.WebBrowser1.GoBack
self.WebBrowser1.GoForward
self.WebBrowser1.Refresh
9.捕捉NewWindow2事件,即新开窗口事件
procedure TForm1.WebBrowser1NewWindow2(Sender: TObject;
var ppDisp: IDispatch; var Cancel: WordBool);
var
NewWindow: TForm2;
begin
//exit;
NewWindow:= TForm2.Create(nil);
NewWindow.Show;
ppDisp:= NewWindow.Webbrowser1.DefaultDispatch;
end; 值得一题的是该方法不能获得新开窗口的URL,退一步的方法只能是等到在新的Webbrowser中触发BeforeNavigate2事件判断了
10.网页中存在iframe时判断页面是否下载结束
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;const pDisp: IDispatch; var URL: OleVariant);
begin
if WebBrowser1.Application = pDisp then showmessage('页面已全部下载完毕')end;
说明一下,每个iframe下载完毕都会触发DocumentComplete事件,所以一个页面在真正下载完毕前可能被触发多次
11. 获取网页中图片//使用DOM模型,什么都能读下来
uses MSHtml, ActiveX;
var
html_doc: IHTMLDocument2;
doc_all : IHtmlElementCollection;
vI : IHtmlImgElement;
begin
html_doc := WebBrowser1.Document as IHTMLDocument2;
doc_all := html_doc.images;
for I := 0 to doc_all.length - 1 do
begin
vI := doc_all.item(I, EMPTYPARAM) as IHtmlImgElement;
//读取vI.src
Memo1.Lines.Add(vI.src);
end;
end;12. 下面函数获得ISomeControl接口var
html_doc: IHTMLDocument2;
doc_all : IHtmlElementCollection;
vI : IHtmlElement;
vD : IDispatch;
begin
html_doc := WebBrowser1.Document as IHTMLDocument2;
doc_all := html_doc.all;
for I := 0 to doc_all.length - 1 do
begin
vI := doc_all.item(I, EMPTYPARAM) as IHtmlElement;
if vI.tagName='OBJECT' then
begin
//读取Classid
Memo1.Lines.Add((vI as IHtmlObjectElement).classid);
//读取包容的对象接口
vD := (vI as IHtmlObjectElement).object_;
...
end;
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment