博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
接收IWebBrowser2的自动化事件
阅读量:6759 次
发布时间:2019-06-26

本文共 4831 字,大约阅读时间需要 16 分钟。

OLE自动化的控制方有时要从受控方接收事件通知。比如WebBrowser的OnNavagiteComplete,OnDocumentComplete等事件。OLE对象需要实现IConnectionPointContainer接口。IConnectionPointContainer和其它几个跟自动化事件相关的接口定义如下:
IEnumConnections = interface
    ['{B196B287-BAB4-101A-B69C-00AA00341D07}']
    function Next(celt: Longint; out elt;
      pceltFetched: PLongint): HResult; stdcall;
    function Skip(celt: Longint): HResult; stdcall;
    function Reset: HResult; stdcall;
    function Clone(out Enum: IEnumConnections): HResult; stdcall;
end;
{ IConnectionPoint interface }
{$EXTERNALSYM IConnectionPoint}
IConnectionPoint = interface
    ['{B196B286-BAB4-101A-B69C-00AA00341D07}']
    function GetConnectionInterface(out iid: TIID): HResult; stdcall;
    function GetConnectionPointContainer(out cpc: IConnectionPointContainer): HResult;
      stdcall;
    function Advise(const unkSink: IUnknown; out dwCookie: Longint): HResult; stdcall;
    function Unadvise(dwCookie: Longint): HResult; stdcall;
    function EnumConnections(out Enum: IEnumConnections): HResult; stdcall;
end;
{ IConnectionPointContainer interface }
{$EXTERNALSYM IConnectionPointContainer}
IConnectionPointContainer = interface
    ['{B196B284-BAB4-101A-B69C-00AA00341D07}']
    function EnumConnectionPoints(out Enum: IEnumConnectionPoints): HResult;
      stdcall;
    function FindConnectionPoint(const iid: TIID;
      out cp: IConnectionPoint): HResult; stdcall;
end;
{ IEnumConnectionPoints interface }
{$EXTERNALSYM IEnumConnectionPoints}
IEnumConnectionPoints = interface
    ['{B196B285-BAB4-101A-B69C-00AA00341D07}']
    function Next(celt: Longint; out elt;
      pceltFetched: PLongint): HResult; stdcall;
    function Skip(celt: Longint): HResult; stdcall;
    function Reset: HResult; stdcall;
    function Clone(out Enum: IEnumConnectionPoints): HResult;
      stdcall;
end;
需要接收自动化事件通知时,可以用InterfaceConnect注册:
procedure InterfaceConnect(const Source: IUnknown; const IID: TGUID;
const Sink: IUnknown; var Connection: Longint);
var
CPC: IConnectionPointContainer;
CP: IConnectionPoint;
begin
Connection := 0;
if Source.QueryInterface(IConnectionPointContainer, CPC)=S_OK then
    if CPC.FindConnectionPoint(IID, CP)=S_OK then
      CP.Advise(Sink, Connection);
end;
其中Source为受控方OLE对象的接口。IID是事件连接点的GUID。一个OLE对象可能有多个事件连接点,比如IWebBrowser2有个时间连接点为:
  
    WebBrowserEventId : TGUID='{34A715A0-6587-11D0-924A-0020AFC7AC4D}';
Sink就是接收事件通知的对象的接口了,这个对象至少需要实现IUnknown和IDispatch接口。当事件触发时,事件接收者的Invoke方法会被调用:
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;Flags: Word; var Params;
VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall;
DispID为事件的编号,可以从自动化对象的事件接口的声明里找到这个编号。比如IWebBrowser的事件声明
   DWebBrowserEvents2 = dispinterface
    ['{34A715A0-6587-11D0-924A-0020AFC7AC4D}']
    procedure StatusTextChange(const Text: WideString); dispid 102;
    procedure ProgressChange(Progress: Integer; ProgressMax: Integer); dispid 108;
    procedure CommandStateChange(Command: Integer; Enable: WordBool); dispid 105;
    procedure DownloadBegin; dispid 106;
    procedure DownloadComplete; dispid 104;
    procedure TitleChange(const Text: WideString); dispid 113;
    procedure PropertyChange(const szProperty: WideString); dispid 112;
    procedure BeforeNavigate2(const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant;
                              var TargetFrameName: OleVariant; var PostData: OleVariant;
                              var Headers: OleVariant; var Cancel: WordBool); dispid 250;
    procedure NewWindow2(var ppDisp: IDispatch; var Cancel: WordBool); dispid 251;
    procedure NavigateComplete2(const pDisp: IDispatch; var URL: OleVariant); dispid 252;
    procedure DocumentComplete(const pDisp: IDispatch; var URL: OleVariant); dispid 259;
    procedure OnQuit; dispid 253;
    procedure OnVisible(Visible: WordBool); dispid 254;
    procedure OnToolBar(ToolBar: WordBool); dispid 255;
    procedure OnMenuBar(MenuBar: WordBool); dispid 256;
    procedure OnStatusBar(StatusBar: WordBool); dispid 257;
    procedure OnFullScreen(FullScreen: WordBool); dispid 258;
    procedure OnTheaterMode(TheaterMode: WordBool); dispid 260;
end;
方法声明后面dispid数字就是DispID。所以如果接收到IWebBrowser2的DispID为259的通知,就表明DocumentComplete事件发生了。
Invoke的Params变参包含特定事件的附加信息,或者叫做事件参数。他是一个TDispParams结构:
tagDISPPARAMS = record
    rgvarg: PVariantArgList;//Variant类型的数组。
    rgdispidNamedArgs: PDispIDList;
    cArgs: Longint; //参数个数
    cNamedArgs: Longint;
end;
对于IWebBrowser2的DocumentComplelte事件,rgvarg[1]就是发出此事件通知的IWebBrowser2接口。请注意,一个内嵌框架下载完成也会触发DocumentComplelte事件,要判断是否整个网页都下载完毕了可以用以下方法(TEventDispatch是我写的一个接收自动化事件通知的类):
function TEventDispatch.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params;
VarResult, ExcepInfo, ArgErr: Pointer): HResult;
var
vPDispParams: PDispParams;
ib:IWebBrowser2;
begin
vPDispParams := PDispParams(@Params);
if DispID=259 then
begin
    if (IDispatch(OleVariant(vPDispParams.rgvarg[1])).QueryInterface(IID_IWebBrowser2,ib)=0) and (ib.Container=nil) then
    begin
      //整个网页下载完成
    end
    else
    begin
      //某个内嵌框架网页下载完成了,但是整个网页没有完成
    end;
end;
Result:= S_OK;
end;
对于IWebBrowser的其它事件我就不再赘述了,可以参考Delphi的TWebBrowser的代码。

转载地址:http://nkbeo.baihongyu.com/

你可能感兴趣的文章
【329】word 替换文本高级用法
查看>>
自动化测试用例编写原则
查看>>
crontab定时任务以及其中中文乱码问题
查看>>
CSAPP buffer lab记录——IA32版本
查看>>
Hyperledger fabric多机的环境部署
查看>>
关于sqlserver2008 bcp根据数据表导出xml格式文件的小记
查看>>
总结:栈和队列的学习
查看>>
线段树(可能还会有树状数组吧)
查看>>
Android应用程序内部启动Activity过程(startActivity)的源代码分析
查看>>
《Python从小白到大牛》第9章 数据结构
查看>>
Xcode中四种build for 的区别
查看>>
酷客多小程序百城宣讲会-嵊州站完美落幕
查看>>
搞机年代,ivvi用“爱情”细分市场
查看>>
思科路由器开机进入 miniIOS 的原因分析
查看>>
卢松松:性格决定网站风格
查看>>
Management Console 工具管理类软件通用开发框架(开放源码)
查看>>
Gnome 3.2 发布计划及新功能
查看>>
已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性...
查看>>
利用bobo-browse 实现lucene的分组统计功能
查看>>
/MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
查看>>