Notice Of Closure

Please note that this website is due to close down on 15th June 2020.

In the interim I will try to move as much content as possible over to my GitHub account. Thanks to everyone who has supported the site over the years.

How to call Delphi code from scripts running in a TWebBrowser (part 3 of 6)

Registering the external object with TWebBrowser

Registering the external object with TWebBrowser

Having implemented the COM object that extends the external object how do we tell the web browser about it?

Further reading
For detailed information about creating a container for TWebBrowser and implementing IOleClientSite and IDocHostUIHandler please see "How to customise the TWebBrowser user interface".

The answer is by creating a container object that hosts the web browser control and implements the IDocHostUIHandler interface. Any web browser control container object must also implement IOleClientSite. IDocHostUIHandler has a GetExternal method. In our implementation of this method we will pass a reference to our custom external object to the browser.

There are numerous other methods of IDocHostUIHandler that we have to implement, but we can get away with stubbing them out. In a previous article (see the "Further reading" box) I discussed IDocHostUIHandler in detail and presented a do nothing implementation – TNulWBContainer. I won't repeat that presentation here, so please check out the earlier article if you need to review how this is done.

Doing all the hard work in TNulWBContainer means that our implementation of IDocHostUIHandler and IOleClientSite, which we will call TExternalContainer, can be quite simple if we descend it from TNulWBContainer. Listing 4 has the declaration of the class, while Listing 5 shows its implementation.

  TExternalContainer = class(TNulWBContainer,
    IDocHostUIHandler, IOleClientSite)
    fExternalObj: IDispatch;  // external object implementation
    { Re-implemented IDocHostUIHandler method }
    function GetExternal(out ppDispatch: IDispatch): HResult; stdcall;
    constructor Create(const HostedBrowser: TWebBrowser);
constructor TExternalContainer.Create(
  const HostedBrowser: TWebBrowser);
  inherited Create(HostedBrowser);
  fExternalObj := TMyExternal.Create;

function TExternalContainer.GetExternal(
  out ppDispatch: IDispatch): HResult;
  ppDispatch := fExternalObj;
  Result := S_OK; // indicates we've provided script

Notice that we create an instance of our external object extension in the constructor and store it in a field of type IDispatch. We then implement GetExternal to pass back a reference to the external object in ppDispatch and return S_OK to indicate we have provided the object.

We pass a reference to the web browser control we are hosting to the constructor. This reference is simply passed on to the inherited constructor where it is recorded and notified that our object is its container. See the implementation of TNulWBContainer.Create for details of how this is done.

We have now completed the code necessary to register the external object with the web browser. In the next section we look at how to call into the external object from JavaScript.