gpt4 book ai didi

delphi - 如何与 TWebBrowser 控件中的 TAutoIntfObject 对象进行互操作?

转载 作者:行者123 更新时间:2023-12-03 15:25:24 24 4
gpt4 key购买 nike

我有一个 TWebBrowser 控件,它实现了 IDocHostUIHandler 以通过 IDispatch 容器扩展 JavaScript 互操作的控制。这工作得很好,只是我不知道如何将事件从 JavaScript 分派(dispatch)回 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,则事件方法已绑定(bind),但 FExtObj 对象引用似乎是在第一个扩展对象方法调用(来自 JavaScript)后释放。

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

很难在这里发布完整的代码,因为它由更多部分组成,here is a complete project用 Delphi 7 制作。

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

最佳答案

使用引用计数,即。将 FExtObj 保留为对接口(interface)的引用,而不是对象:

  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;

关于delphi - 如何与 TWebBrowser 控件中的 TAutoIntfObject 对象进行互操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15971871/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com