加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 如何从TWebBrowser控件中与TAutoIntfObject对象互操作

发布时间:2020-12-15 09:25:45 所属栏目:大数据 来源:网络整理
导读:我有一个TWebBrowser控件,它实现了IDocHostUIHandler,以通过IDispatch容器扩展 JavaScript互操作的控制.这工作正常,除了我不知道,如何将事件从JavaScript调度回Web浏览器控件. 扩展对象是一个基于TAutoIntfObject的容器,如 this example 所示.正如您在示例中
我有一个TWebBrowser控件,它实现了IDocHostUIHandler,以通过IDispatch容器扩展 JavaScript互操作的控制.这工作正常,除了我不知道,如何将事件从JavaScript调度回Web浏览器控件.

扩展对象是一个基于TAutoIntfObject的容器,如this example所示.正如您在示例中所看到的,没有与Web浏览器控件的互操作.理想情况下,我想在该扩展对象上实现事件,但我不知道如何在我的Web浏览器控件中正确声明TAutoIntfObject对象.假设我有这个扩展对象:

type
  TZoomChangeEvent = procedure(Sender: TObject; ZoomLevel: Integer) of object;
  TOpenLayersExt = class(TAutoIntfObject,IOpenLayers)
  private
    FOnZoomChange: TZoomChangeEvent;
    // the ZoomChange method is invoked from JavaScript
    procedure ZoomChange(ZoomLevel: Integer); safecall;
  public
    property OnZoomChange: TZoomChangeEvent read FOnZoomChange write FOnZoomChange;
  end;

implementation

procedure TOpenLayersExt.ZoomChange(ZoomLevel: Integer);
begin
  if Assigned(FOnZoomChange) then
    FOnZoomChange(Self,ZoomLevel);
end;

这样的TWebBrowser控件:

type
  TMapBrowser = class(TWebBrowser,IDocHostUIHandler)
  private
    // the extension object
    FExtObj: TOpenLayersExt;
    // IDocHostUIHandler::GetExternal method
    function GetExternal(out ppDispatch: IDispatch): HRESULT; stdcall;
    // this is the TOpenLayersExt.OnZoomChange event method implementation
    procedure OnZoomChange(Sender: TObject; Zoom: Integer);
  public
    // ordinary constructor
    constructor Create(AOwner: TComponent); override;
  end;

implementation

constructor TMapBrowser.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  // create extension object
  FExtObj := TOpenLayersExt.Create;
  // here the event method is properly binded; if I'd change the FExtObj type
  // to IDispatch with TOpenLayersExt(FExtObj) typecast,it wouldn't
  FExtObj.OnZoomChange := OnZoomChange;
end;

function TMapBrowser.GetExternal(out ppDispatch: IDispatch): HRESULT;
begin
  // the problem is that I don't know how to properly pass this object to the
  // ppDispatch parameter; if this GetExternal method is called second time,// the FExtObj seems to be released,but I don't get why
  ppDispatch := FExtObj as IDispatch;
  Result := S_OK;
end;

问题是,如果我将FExtObj对象声明为TOpenLayersExt,则事件方法被绑定,但是在第一个扩展对象方法调用(来自JavaScript)之后,似乎释放了FExtObj对象引用.

如果我将其声明为IDispatch,则在调用JavaScript函数后不会释放引用,但OnZoomChange事件未绑定.

很难在这里发布完整的代码,因为它是由Delphi 7制作的更多部分组成的.

所以我的问题是,如何在Web浏览器控件中使用来自TAutoIntfObject扩展对象的事件;如何声明扩展对象,所以我将能够处理来自Web浏览器控件的事件并将其传递给仍然保持接口对象引用的IDocHostUIHandler :: GetExternal方法参数?

解决方法

使用引用计数,即.保持FExtObj作为对接口的引用,而不是对象:

private
    // the extension object
    FExtObj: IDispatch;

constructor TMapBrowser.Create(AOwner: TComponent);
var
  AExtObj: TOpenLayersExt;
begin
  inherited Create(AOwner);
  // create extension object
  AExtObj := TOpenLayersExt.Create;
  AExtObj.OnZoomChange := OnZoomChange;
  FExtObj := AExtObj as IDispatch;
end;

destructor TMapBrowser.Destroy;
begin
  FExtObj := nil;
  inherited Destroy;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读