TLa*_*ama 4 delphi twebbrowser
我有一个TWebBrowser控件,它实现IDocHostUIHandler了通过IDispatch容器扩展JavaScript互操作的控制.这工作正常,除了我不知道,如何将事件从JavaScript调度回Web浏览器控件.
扩展对象是基于TAutoIntfObject类似的容器this example.正如您在示例中所看到的,没有与Web浏览器控件的互操作.理想情况下,我想在该扩展对象上实现事件,但我不知道如何TAutoIntfObject在我的Web浏览器控件中正确声明该对象.假设我有这个扩展对象:
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;
Run Code Online (Sandbox Code Playgroud)
和这样的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;
Run Code Online (Sandbox Code Playgroud)
问题是,如果我将FExtObj对象声明为TOpenLayersExt,则事件方法被绑定,但是FExtObj在第一个扩展对象方法调用(来自JavaScript)之后,对象引用似乎被释放.
如果我将其声明为IDispatch,则在JavaScript函数调用后不会释放引用,但该OnZoomChange事件未绑定.
很难在这里发布完整的代码,因为它是由here is a complete projectDelphi 7中的更多部分组成的.
所以我的问题是,如何TAutoIntfObject在Web浏览器控件中使用扩展对象中的事件; 如何声明扩展对象,所以我将能够处理来自Web浏览器控件的事件并将其传递给IDocHostUIHandler::GetExternal仍然保持接口对象引用的方法参数?
使用引用计数,即.保持FExtObj作为对接口的引用,而不是对象:
private
// the extension object
FExtObj: IDispatch;
Run Code Online (Sandbox Code Playgroud)
...
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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |