Interface tool

 

IEGUID Unit

IEGUID is a small unit that makes it easier to work with the webbrowser component.

When you start Delphi-programming with the Webbrowser component, you will soon find that many important header-files still are not converted to Delphi. So if you for instance need the service identifier SID_STopLevelBrowser you will not find it declared in the Delphi source-files. You will have to search in the c++ headerfiles available from MS-site. There you will find SID_SToplLevelBrowser in shlguid.h:

 DEFINE_GUID(SID_STopLevelBrowser, 0x4C96BE40L, 0x915C, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37);

So now you have to translate it to Delphi

SID_STopLevelBrowser : TGUID = '{4C96BE40-915C-11CF-99D3-00AA004AE837}';

before you can continue, unless you already have forgotten why you needed it in the first place.

You can use the function CreateGuidList i IEGuid.pas to collect GUIDs from headerfiles and from registered interfaces in your registry database.

If you have downloaded IE 5.5  and Win2000 header-files it collects between 4000 and 5000 GUID's  and place them in a textfile in the following format:

IWebbrowserApp={0002DF05-0000-0000-C000-000000000046}

The GUID-list is not only useful for having easy access to the declarations. It is also useful if you have an interface and you don't know what other interfaces you can obtain. Just call queryinterface with all the GUIDs in the list, and see if for which of them  S_OK is returned.

Follow these steps to create your GUID-list:

1) Download IE 5.5 Header-files

2) Download Windows 2000 Header-files.

Dont use old header-files. Even if you run IE4 on WIN95.

3) Copy all the .h-files into a temporary directory (e.g. C:\headers).

4) Call CreateGuidList-function in IEGuid.pas:

function CreateIEGuid('C:\headers', 'C:\MyGuidList.txt') : Integer;


First parameter is the directory where your header-files are placed. The second parameter the output file. The function returns the number of GUID's collected.

Note that this raw Guid-list contains all kind of identifiers: Service identifiers (SID_) , class identifier (CLSID_), interface identifiers (IID_) etc. It also contains identical Guids with different names, since e.g.:

SID_SHLinkFrame = IID_IHLinkFrame = IHLinkFrame

I have included at quick function CreateIEList that selects the GUIDs  must interesting when working with the webbrowser. In the following demos the output-file of this function (ielist.txt) is used.  

 

procedure TForm1.Button1Click(Sender: TObject);
begin
Showmessage('GUID's found: '+inttoStr(CreateIEGuid('c:\headers','c:\guidlist.txt')));
Showmessage('Sorted GUID's: '+inttoStr(CreateIEList('c:\guidlist.txt','c:\ieguidlist.txt')));
end;


Hunting Interfaces

You probably know that you can use QueryInterface to obtain certain interfaces on Webbrowser1 or Webbrowser1.Application or Webbrowser1.Document. But it is not easy to get a clear picture of what kind of interfaces you can obtain.

The Guid-list is helpful here. Place a memo-field and a button on a form and add IEGuid.pas in the uses-section. MyGuids.Create(NameofYourGuidList) loads your guid-list and place them in two stringlists: MyGuids.Names and MyGuids.Guids. The first list contains the name of the identifier and the latter the guid-string. So to create a list of interfaces you can query for on Webbrowser1.Application you just have to add this code:

 

uses shdocvw (or shdocvw_tlb), IEGuid;

var
MyGuids: TIEGuid;

procedure TForm1.Button1Click(Sender: TObject);
var
Counter: Integer;
i: IUnknown;
wb: Twebbrowser;
begin
WB := Twebbrowser.Create(self);
MyGuids.GetInterfaces(wb.Application, memo1.lines);
WB.free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MyGuids := TIEGuid.Create('C:\IEGuidList.txt');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
MyGuids.Free;
end;


If you use IE 5.5 and the IEList.txt (created with CreateIEList), your memo1 will show the following interfaces:

IConnectionPointContainer
IDataObject
IDispatch
IExternalConnection
IHlinkFrame
IInternetSecurityMgrSite
IObjectSafety
IOleCommandTarget
IOleControl
IOleInPlaceActiveObject
IOleInPlaceObject
IOleObject
IOleWindow
IPersist
IPersistHistory
IPersistPropertyBag
IPersistStorage
IPersistStream
IPersistStreamInit
IProvideClassInfo
IProvideClassInfo2
IServiceProvider
ITargetFrame
ITargetFrame2
ITargetNotify
IUnknown
IUrlHistoryNotify
IViewObject
IViewObject2
IWebBrowser
IWebBrowser2
IWebBrowserApp

Of course you can do the same on all other interfaces. Remember to load a document in the webbrowser before trying to query on Webbrowser1.document. 

You now have a list of interfaces you can get from Webbrowser1.Application. If you want a Serviceprovider you can use: 

MyServiceProvider:=Webbrowser1.Application as IServiceprovider;

or 

MyServiceProvider:=IServiceprovider(Webbrowser1.Application);

or

Webbrowser1.Application.QueryInterface(IServiceprovider, MyServiceProvider);

You can also use the IEGuid to search interfaces that can be obtained using IServiceprovider(Webbrowser.Application).QueryService. In the following sample we use the IEguid to get some information about the the service-group SID_STopLevelBrowser:

 

procedure TForm1.Button2Click(Sender: TObject);
var
  wb: Twebbrowser;
begin
  WB := Twebbrowser.Create(self);
  MyGuids.GetServices(wb.Application,'SID_STOPLEVELBROWSER', memo1.lines);
  WB.free;
end;


This time the result looks like this:

IAdviseSink
IDropTarget
IInputObjectSite
IInternetSecurityMgrSite
IOleCommandTarget
IOleContainer
IOleInPlaceUIWindow
IOleWindow
IPersistHistory
IProfferService
IServiceProvider
IShellBrowser
IUnknown
IUrlHistoryStg
IVersionHost

Leave second parameter empty if you want a list for services, where rsid is equal to iid (e.g. QueryService(IHtmlwindow2, IHtmlWindow2, unk):

  MyGuids.GetServices(wb.Application,'', memo1.lines);

It is now easy to find the right interface and call the methods you want. If you need to call IHtmlWindow2s method Confirm to show a dialogbox it only is a few lines of code away:


1. QueryInterface Webbrowser1.Application for ServiceProvider.
2. Queryservice for IHTMLWindow2.
3. Call IHtmlWindow2.confirm.

or using typecasting:

var
IHW: IHtmlwindow2;
begin
(Embeddedwb1.Application as IServiceprovider).QueryService(IhtmlWindow2,IhtmlWindow2, IHW);
IHW.confirm('This is a dialogbox!');
end;


Microsoft website includes documentation for many of the interfaces and their methods, but since many header-files not yet are converted to Delphi you might need to convert them yourself. 

First search the Delphi-Jedi Projects WINAPI library to see if it already has been converted by someone else. Or download these excellent tutorials on converting C++ header-files to Delphi:

Project JEDI Conversion Tutorial
Dr Bob's header conversion articles

Outgoing Interfaces

On Webbrowser1.Application we could query for IConnectionPointContainer so we can also use the guidlist to get a list of outgoing interfaces as well:

procedure TForm1.Button2Click(Sender: TObject);
var
  wb: Twebbrowser;
begin
  WB := Twebbrowser.Create(self);
   MyGuids.GetConnectionpoints(wb.Application,memo1.lines, TRUE);
   WB.free;
end;

The result is perhaps not a big surprise:

DWebBrowserEvents2
DWebBrowserEvents
IPropertyNotifySink

and on Webbrowser.Document:

IPropertyNotifySink
HTMLDocumentEvents
HTMLDocumentEvents2
ITridentEventSink
IDispatch

 

Use your own implementations

To study what goes on behind the scene when the webbrowser is running, you can use the guidlist in the OnQueryService eventhandler in EmbeddedWB:

function TForm1.EmbeddedWB1QueryService(const rsid, iid: TGUID;
out Obj: IUnknown): HRESULT;
begin
Memo1.Lines.Add(MyGuids.NameFromGuid(rsid)+' - '+MyGuids.NameFromGuid(iid));
Result:=E_NOINTERFACE;
end;

 The result output may look like this:

ITargetFrame2 - {9216E421-2BF5-11D0-82B4-00A0C90C29C5}
SID_STopWindow - ISearchContext
ITargetFrame2 - IUnknown
SID_STopLevelBrowser - IOleCommandTarget
SID_STopLevelBrowser - {DFEED31E-78ED-11D2-86BA-00C04F8EEA99}
SID_STopLevelBrowser - IServiceProvider
SID_STopLevelBrowser - IServiceProvider
IMimeInfo - IMimeInfo
SID_STopLevelBrowser - IOleCommandTarget
{639447BD-B2D3-44B9-9FB0-510F23CB45E4} - {639447BD-B2D3-44B9-9FB0-510F23CB45E4}
SID_STopLevelBrowser - IOleWindow
ITargetFrame2 - IUnknown
SID_STopLevelBrowser - IOleCommandTarget
SID_STopLevelBrowser - IUrlHistoryStg
IOleUndoManager - IOleUndoManager
IInternetSecurityManager - IInternetSecurityManager
SID_STopLevelBrowser - IServiceProvider
HTMLFrameBase - HTMLFrameBase
{AD7F6C62-F6BD-11D2-959B-006097C553C8} - IUnknown
{6D12FE80-7911-11CF-9534-0000C05BAE0B} - IUnknown
IElementBehaviorFactory - IElementBehaviorFactory
{371EA634-DC5C-11D1-BA57-00C04FC2040E} - IVersionHost
IInternetProtocol - IInternetProtocol
ITargetFrame2 - IUnknown
SID_STopLevelBrowser - IServiceProvider
SID_STopLevelBrowser - IOleCommandTarget
SID_STopLevelBrowser - IUrlHistoryStg
SID_STopLevelBrowser - IShellBrowser
IActiveScriptSite - IOleCommandTarget
SID_GetCaller - IServiceProvider
SID_STopLevelBrowser - IOleCommandTarget
SID_SEditCommandTarget - IOleCommandTarget
SID_STopLevelBrowser - IShellBrowser
SID_SEditCommandTarget - IOleCommandTarget
ITargetFrame2 - IUnknown
SID_SEditCommandTarget - IOleCommandTarget
IHTMLEditHost - IHTMLEditHost

Here you also have a chance to hand the webbrowser your own version of the interface it is asking for.

For more info see the included IEGuid Demo.

Enjoy!

 

 

Download IEGUID Unit

IEGUID  (incl. demo)  Delphi 5


Created and maintained by
Per Lindsų Larsen

Last Update: October 15, 2000