您的位置:首页 > 编程语言 > Delphi

Delphi中挂接IWebBrowser2的自动化事件

2016-07-27 18:18 351 查看


(2010-12-20 20:36:27)


转载▼

标签:

delphi

it

分类:
软件设计
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

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;

本文来自Delphi之窗,原文地址:http://www.52delphi.com/list.asp?ID=1208
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: