WebBrowser组件和MSHTML 在Delphi中的使用
由于项目需要,近来研究了一下WebBrowser组件和MSHTML 在Delphi中的使用,整理了一下这段时间研究的结果,写下来一是方便大家查阅,二也可以加深我自己的记忆.希望能对大家有所帮助… …,同时,如果有更好的处理方式或者我没有提到的问题,请大家也告诉我哦, 咱们一块进步… ...,其中一部分是我从网络中搜集的资料,谢谢那些兄弟们… …
MSHTML把HTML页面中的元素封装成了IHTMLInputElement、 IHTMLInputButtonElement、IHTMLInputTextElement、IHTMLTextAreaElement、IHTMLTitleElement、IHTMLFormElement等等组件接口。
在程序中可以通过MSHTML提供的IHTMLDocument2接口得到整个Document对象,IHTMLElementCollection接口得到所有页面元素的集合,通过该接口的Item方法可以得到具体的某个组件,然后设置和读取该组件的属性值。
下面是一些常用功能的事例代码.
1. 打开某个页面:
web.Navigate(ExtractFilePath(Application.ExeName) + 'Template/login.html');
2. 取出页面中某个HtmlElement的Value属性值:
MSHTML把HTML页面中的元素封装成了IHTMLInputElement、 IHTMLInputButtonElement、IHTMLInputTextElement、IHTMLTextAreaElement、IHTMLTitleElement、IHTMLFormElement等等组件接口。
在程序中可以通过MSHTML提供的IHTMLDocument2接口得到整个Document对象,IHTMLElementCollection接口得到所有页面元素的集合,通过该接口的Item方法可以得到具体的某个组件,然后设置和读取该组件的属性值。
下面是一些常用功能的事例代码.
1. 打开某个页面:
web.Navigate(ExtractFilePath(Application.ExeName) + 'Template/login.html');
2. 取出页面中某个HtmlElement的Value属性值:
function GetValueByElementName(web: TWebBrowser; elementName: string; index: integer): string;
begin
result := (((web.Document as IHTMLDocument2).body.all as
IHTMLElementCollection).item(elementName, index) as IHTMLInputElement
).value
end;
3. 给HtmlElement设置Value属性
procedure SetValueTextAreaName(web: TWebBrowser; elementName, value: string;index: integer);
begin
(((web.Document as IHTMLDocument2).body.all as
IHTMLElementCollection).item(elementName, index) as IHTMLTextAreaElement
).value := value;
end;
begin
result := (((web.Document as IHTMLDocument2).body.all as
IHTMLElementCollection).item(elementName, index) as IHTMLInputElement
).value
end;
3. 给HtmlElement设置Value属性
procedure SetValueTextAreaName(web: TWebBrowser; elementName, value: string;index: integer);
begin
(((web.Document as IHTMLDocument2).body.all as
IHTMLElementCollection).item(elementName, index) as IHTMLTextAreaElement
).value := value;
end;
4. 判断页面执行结果是否成功
因为Web应用中如果出错的一般是采用错误页面的方式呈现给最终用户,所以我们也无法抓到Http错误,只能通过在webBeforeNavigate2事件中将URL参数记录到全局变量中, 然后在webDocumentComplete事件中根据URL参数和全局变量中的URL参数来判断执行结果是否正确.当然,这样需要将页面地址编码到代码中,降低了灵活性,但是这也是我能想到的唯一的方法,如果大家有什么好的方法,请告诉我哦.
5. 屏蔽鼠标右键和某些快捷键
本功能需要在webBrowser的窗口中加入ApplicationEvents组件,设置它的OnMessage事件代码如下即可.
procedure TwebAdapterForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
const
_KeyPressMask = $80000000;
begin
//禁用右键
因为Web应用中如果出错的一般是采用错误页面的方式呈现给最终用户,所以我们也无法抓到Http错误,只能通过在webBeforeNavigate2事件中将URL参数记录到全局变量中, 然后在webDocumentComplete事件中根据URL参数和全局变量中的URL参数来判断执行结果是否正确.当然,这样需要将页面地址编码到代码中,降低了灵活性,但是这也是我能想到的唯一的方法,如果大家有什么好的方法,请告诉我哦.
5. 屏蔽鼠标右键和某些快捷键
本功能需要在webBrowser的窗口中加入ApplicationEvents组件,设置它的OnMessage事件代码如下即可.
procedure TwebAdapterForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
const
_KeyPressMask = $80000000;
begin
//禁用右键
with Msg do
begin
if not IsChild(web.Handle, hWnd) then Exit;
Handled := (message = WM_RBUTTONDOWN) or (message = WM_RBUTTONUP) or (message = WM_CONTEXTMENU);
end;
//禁止Ctrl + N
//禁止Ctrl + F
//禁止Ctrl + A
ssage = WM_KEYDOWN then
begin
if ((Msg.lParam and _KeyPressMask) = 0) and
(GetKeyState(VK_Control) <0) and ((Msg.wParam = Ord('N'))
or (Msg.wParam = Ord('F')) or (Msg.wParam = Ord('A'))) then
begin
begin
if not IsChild(web.Handle, hWnd) then Exit;
Handled := (message = WM_RBUTTONDOWN) or (message = WM_RBUTTONUP) or (message = WM_CONTEXTMENU);
end;
//禁止Ctrl + N
//禁止Ctrl + F
//禁止Ctrl + A
ssage = WM_KEYDOWN then
begin
if ((Msg.lParam and _KeyPressMask) = 0) and
(GetKeyState(VK_Control) <0) and ((Msg.wParam = Ord('N'))
or (Msg.wParam = Ord('F')) or (Msg.wParam = Ord('A'))) then
begin
Handled := True;
end;
end;
end;
6. 在页面关闭的时候,同时关掉包含页面的VCL Form.(仅限 InternetExplorer 6.0)
本功能需要卸载掉Delphi自带的 WebBrowser组件,安装ActionX组件(Microsoft Internet Controls V1.1),而且以后的程序只能运行在安装有Internet Explorer 6.0 的环境下.具体方法如下:
在WebBrowser组件的OnWindowClosing事件中,输入self.close; 代码即可.如果需要阻止窗口的关闭, 设置CanClose参数的值为Flase.
7. 如何将页面中超链接新开的页面窗口包到指定的VCL窗口中.
procedure TForm1.webNewWindow2(Sender: TObject; var ppDisp: IDispatch;
var Cancel: WordBool);
var
form : TForm1;
end;
end;
end;
6. 在页面关闭的时候,同时关掉包含页面的VCL Form.(仅限 InternetExplorer 6.0)
本功能需要卸载掉Delphi自带的 WebBrowser组件,安装ActionX组件(Microsoft Internet Controls V1.1),而且以后的程序只能运行在安装有Internet Explorer 6.0 的环境下.具体方法如下:
在WebBrowser组件的OnWindowClosing事件中,输入self.close; 代码即可.如果需要阻止窗口的关闭, 设置CanClose参数的值为Flase.
7. 如何将页面中超链接新开的页面窗口包到指定的VCL窗口中.
procedure TForm1.webNewWindow2(Sender: TObject; var ppDisp: IDispatch;
var Cancel: WordBool);
var
form : TForm1;
begin
form := TForm1.Create(nil);
ppDisp := form.web.DefaultDispatch;
form.Show;
end;
8. 在WebBrowser加载html页面完成后,在页面顶端插入HTML代码, 下面两种方式斗可以.
{1. ----------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
Range: IHTMLTxtRange;
begin
Range := ((WebBrowser1.Document as IHTMLDocument2).body as
IHTMLBodyElement).createTextRange;
llapse(False);
form := TForm1.Create(nil);
ppDisp := form.web.DefaultDispatch;
form.Show;
end;
8. 在WebBrowser加载html页面完成后,在页面顶端插入HTML代码, 下面两种方式斗可以.
{1. ----------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
Range: IHTMLTxtRange;
begin
Range := ((WebBrowser1.Document as IHTMLDocument2).body as
IHTMLBodyElement).createTextRange;
llapse(False);
Range.pasteHTML('<br/><b>Hello!</b>');
end;
{2. ----------------------------------------------------------------}
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
WebDoc: HTMLDocument;
WebBody: HTMLBody;
begin
WebDoc := WebBrowser1.Document as HTMLDocument;
WebBody := WebDoc.body as HTMLBody;
WebBody.insertAdjacentHTML('BeforeEnd', '<h1>Hello World!</h1>');
end;
9. 将页面中显示的内容全部选中,然后粘贴到Word文档中.
WebBrowser1.ExecWB(OLECMDID_SELECTALL, OLECMDEXECOPT_DODEFAULT);//
end;
{2. ----------------------------------------------------------------}
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
WebDoc: HTMLDocument;
WebBody: HTMLBody;
begin
WebDoc := WebBrowser1.Document as HTMLDocument;
WebBody := WebDoc.body as HTMLBody;
WebBody.insertAdjacentHTML('BeforeEnd', '<h1>Hello World!</h1>');
end;
9. 将页面中显示的内容全部选中,然后粘贴到Word文档中.
WebBrowser1.ExecWB(OLECMDID_SELECTALL, OLECMDEXECOPT_DODEFAULT);//
全选网页
WebBrowser1.ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT); //复制网页
WordDocu.Range.Paste; //word文档粘贴
WebBrowser1.ExecWB(OLECMDID_UNDO, OLECMDEXECOPT_DODEFAULT); //取消全选
注:WebBrowser的Document属性值和WordDocument的Document属性值必须都不为nil.
10. 如何解决网页不响应回车事件
public
{ Public declarations }
procedure MsgHandle(var Msg :TMsg; var Handled :Boolean);
end;
var
Form1: TForm1;
FOleInPlaceActiveObject :IOleInPlaceActiveObject;
WebBrowser1.ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT); //复制网页
WordDocu.Range.Paste; //word文档粘贴
WebBrowser1.ExecWB(OLECMDID_UNDO, OLECMDEXECOPT_DODEFAULT); //取消全选
注:WebBrowser的Document属性值和WordDocument的Document属性值必须都不为nil.
10. 如何解决网页不响应回车事件
public
{ Public declarations }
procedure MsgHandle(var Msg :TMsg; var Handled :Boolean);
end;
var
Form1: TForm1;
FOleInPlaceActiveObject :IOleInPlaceActiveObject;
implementation
{$R *.DFM}
procedure TForm1.MsgHandle(var Msg :TMsg; var Handled :Boolean);
var
iOIPAO :IOleInPlaceActiveObject;
Dispatch :IDispatch;
begin
if WebBrowser1 =nil then
begin
Handled :=False;
Exit;
end;
Handled :=(IsDialogMessage(WebBrowser1.Handle, Msg) =True);
if (Handled) and (not WebBrowser1.Busy) then
begin
{$R *.DFM}
procedure TForm1.MsgHandle(var Msg :TMsg; var Handled :Boolean);
var
iOIPAO :IOleInPlaceActiveObject;
Dispatch :IDispatch;
begin
if WebBrowser1 =nil then
begin
Handled :=False;
Exit;
end;
Handled :=(IsDialogMessage(WebBrowser1.Handle, Msg) =True);
if (Handled) and (not WebBrowser1.Busy) then
begin
if FOleInPlaceActiveObject =nil then
begin
Dispatch :=WebBrowser1.Application;
if Dispatch <>nil then
begin
Dispatch.QueryInterface(IOleInPlaceActiveObject, iOIPAO);
if iOIPAO <>nil then
FOleInPlaceActiveObject :=iOIPAO;
end;
end;
end;
if FOleInPlaceActiveObject <>nil then
if ((ssage =WM_KEYDOWN) or (Msg.Message =WM_KEYUP)) and ((Msg.wParam =VK_BACK) or (Msg.wParam =VK_LEFT) or (Msg.wParam =VK_RIGHT)) then
begin
Dispatch :=WebBrowser1.Application;
if Dispatch <>nil then
begin
Dispatch.QueryInterface(IOleInPlaceActiveObject, iOIPAO);
if iOIPAO <>nil then
FOleInPlaceActiveObject :=iOIPAO;
end;
end;
end;
if FOleInPlaceActiveObject <>nil then
if ((ssage =WM_KEYDOWN) or (Msg.Message =WM_KEYUP)) and ((Msg.wParam =VK_BACK) or (Msg.wParam =VK_LEFT) or (Msg.wParam =VK_RIGHT)) then
else
FOleInPlaceActiveObject.TranslateAccelerator(Msg);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage :=MsgHandle;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FOleInPlaceActiveObject :=nil;
end;
11. 如何在WebBrowser中调用当前页面中的javascript函数SayHello()
WebBrowser1.OleObject.
Script('SayHello()', 'javascript');
//or
FOleInPlaceActiveObject.TranslateAccelerator(Msg);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage :=MsgHandle;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FOleInPlaceActiveObject :=nil;
end;
11. 如何在WebBrowser中调用当前页面中的javascript函数SayHello()
WebBrowser1.OleObject.
Script('SayHello()', 'javascript');
//or
(WebBrowser1.Document as IHTMLDocument2
).Script('SayHello()', 'javascript')
//or
webrowser1.document.script.SayHello();
).Script('SayHello()', 'javascript')
//or
webrowser1.document.script.SayHello();
delphi中Webbrowser的使用技巧
1.获取网页中变量的值
例如:htm中<script> var currIDS=123</script>
程序中可以这样调用 id := Form1.WebBrowser1.OleObject.Document.script.currIDS
备注:变量可以是javascript定义的,也可以是vbscript定义的,如果Webbrowser1中不到该变量,调用会触发一个异常事件,即变量currIDS不存在。
例如:htm中<script> var currIDS=123</script>
程序中可以这样调用 id := Form1.WebBrowser1.OleObject.Document.script.currIDS
备注:变量可以是javascript定义的,也可以是vbscript定义的,如果Webbrowser1中不到该变量,调用会触发一个异常事件,即变量currIDS不存在。
2.执行网页中的函数
tmpf := 'currID = getNextID(currID)'+#13#10;
Form1.WebBrowser1.OleObject.Script(tmpf,'JavaScript');
tmpf := 'currID = getNextID(currID)'+#13#10;
Form1.WebBrowser1.OleObject.Script(tmpf,'JavaScript');
调用函数的方法就是execScript接口,同样,如果函数不存在,或者运行错误也会触发脚本错误异常
3.设置网页背景
背景图片 WebBrowser1.OleObject.Document.body.background := 'seelearn/bg.gif' ;
背景颜 WebBrowser1.OleObject.Document.body.bgcolor := '#eeeeee'
背景图片 WebBrowser1.OleObject.Document.body.background := 'seelearn/bg.gif' ;
背景颜 WebBrowser1.OleObject.Document.body.bgcolor := '#eeeeee'
4.调用网页中已知对象
src := WebBrowser1.ElementByID('img1').src
该方法其实就是javascript中的 getElementByID
src := WebBrowser1.ElementByID('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);
使用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重新初始化。
这是一个让人很意外的一个问题,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>点点博客 seelearn</font></p>';
SetNoteStr :=SetNoteStr+'<br><p align=center><font size=+2 color=#FFFFFF>点击左边按钮可查看对应图片</font></p>';
StrStream:=TStringStream.Create(SetNoteStr);
var
StrStream:TStringStream;
SetNoteStr: string;
begin
SetNoteStr :='<body bgcolor=222222 align=center><br><p align=center><font size=+2 color=#FFFFFF>点点博客 seelearn</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;
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
self.WebBrowser1.GoBack
self.WebBrowser1.GoForward
self.WebBrowser1.Refresh
9.捕捉NewWindow2事件,即新开窗口事件
procedure TForm1.WebBrowser1NewWindow2(Sender: TObject;
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;
html document是什么 值得一题的是该方法不能获得新开窗口的URL,退一步的方法只能是等到在新的Webbrowser中触发BeforeNavigate2事件判断了
var
NewWindow: TForm2;
begin
//exit;
NewWindow:= TForm2.Create(nil);
NewWindow.Show;
ppDisp:= NewWindow.Webbrowser1.DefaultDispatch;
end;
html document是什么 值得一题的是该方法不能获得新开窗口的URL,退一步的方法只能是等到在新的Webbrowser中触发BeforeNavigate2事件判断了
10.网页中存在iframe时判断页面是否下载结束
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
begin
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
begin
if WebBrowser1.Application = pDisp then showmessage('页面已全部下载完毕')
end;
end;
备注:每个iframe下载完毕都会触发DocumentComplete事件,所以一个页面在真正下载完毕前可能被触发多次
Delphi中使用WebBrowser控件中载入的页面的script
使用如下语句即可:
webrowser1.OleObject.document.script.doSomething(parameter);
webrowser1.OleObject.document.script.doSomething(parameter);
在网上看到还可以如下使用,不过我没用过。
uses MSHTML; //use IHTMLDocument2
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
WebBrowser1.OleObject.
Script('SayHello()', 'javascript');
//or
(WebBrowser1.Document as IHTMLDocument2 ).Script('SayHello()', 'javascript')
end;
用WebBrowser实现HTML界面的应用
HTML的界面有以下特点:图文混排,格式灵活,可以包含Flash、声音和视频等,实现图文声像的多媒体界面,而且易于建立和维护。另外,HTML的显示环境一般机器上都具备,通常不需要安装额外的软件。当然,HTML界面也有它欠缺的方面,即:界面控制能力有限,代码调试不便----虽然DHTML提供了比较强的编程特性,但是比起Delphi的传统的开发语言和工具来,对界面的控制能力,尤其是和数据交互时的控制能力还是稍逊一筹。
了解了这些特点,我们就可以在实际应用开发中,适时地选择HTML技术。下面举个例子:
一种仪器的管理程序,需要显示该仪器的操作方法文档,包含文字和图片,并要求可以隐藏或显示文档,并能安要求打印。
这个应用中,图文显示、隐藏/显示部分文档、图文打印等需求,都是HTML界面所擅长的,用传统的表单控件实现几乎无法想像。
用什么实现HTML的界面
用Delphi实现HTML界面的应用主要有两种选择:WebBrowser Control或MSHTML。为了弄清两者如何选择,我们先来看看Internet Exporer 4.0及其后续版本的体系结构:
IE浏览器是建立在SHDOCVW.DLL组件之上的,而SHDOCVW.DLL则建立在MSHTML.DLL组件之上,底层则包括脚本引擎等。SHDOCVW.DLL提供了对活动文档(Active Document)的支持----例如Word等文档可以在IE中显示,并提供导航、in-place*连接、收藏夹、浏览历史和分级内容选择(PICS: Platform for Internet Content Selection)等功能。SHDOCVW.DLL组件虽然也提供了很多接口可以单独使用,但是通常所指的SHDOCVW.DLL就是WebBrowser Control。MSHTML.DLL是实行HTML解析和表现的组件。
它通过DHTML对象模型提供对HTML文档的访问。它实现了活动文档服务器接口,可以通过COM接口调用。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论