我有一个实现
扩展对象是基于
问题在于,如果我将
如果我将其声明为
由于代码由多个部分组成,因此很难在此处发布完整代码,
因此,我的问题是如何从Web浏览器控件中消耗
IDocHostUIHandler
的TWebBrowser
控件,通过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
方法参数,同时保持接口对象引用?
how the IOleClientSite
在那里起到了什么作用。每当您通过external
从JavaScript调用方法时,IDocHostUIHandler::GetExternal
方法会请求一个外部对象,该对象必须具有您正在调用的名称的分派方法。这里不需要IOleClientSite
。关于EWB,它如何帮助我?只有一个OnGetExternal
事件,在其中传递扩展容器,但这正是我所拥有的。 - TLamaTExternalContainer = class(TNulWBContainer, IDocHostUIHandler, IOleClientSite)
,在主项目中fContainer := TExternalContainer.Create(WebBrowser1);
。这有点棘手,但实际上是一个非常好的想法,可以避免像你所做的那样使用中介类:TMapBrowser = class(TWebBrowser, IDocHostUIHandler)
。 - kobik