The TWebBrowser Delphi component provides access to the Web browser functionality from your Delphi applications.
In most situations you use the TWebBrowser to display HTML documents to the user - thus creating your own version of the (Internet Explorer) Web browser. Note that the TWebBrowser can also display Word documents, for example.
A very nice feature of a Browser is to display link information, for example, in the status bar, when the mouse hovers over a link in a document.
The TWebBrowser does not expose an event like "OnMouseMove". Even if such an event would exist it would be fired for the TWebBrowser component - NOT for the document being displayed inside the TWebBrowser.
In order to provide such information (and much more, as you will see in a moment) in your Delphi application using the TWebBrowser component, a technique called "events sinking" must be implemeted.
WebRenderer - Java SDKJava HTML and Multimedia component HTML 4.01, CSS, XSL, XML, SSLwww.webrenderer.com
Convert data to XMLCredibleXML-award winning software New V2.1 Supports .NET & Javawww.crediblexml.com/
Delphi XML componentDownload native Delphi XML parser and writer (source available)www.simdesign.nl/xml.html
To get the "href" attribute (link) of an "a" tag inside a document, while the mouse hovers over a document, you need to react on the "onmousemove" event of the IHTMLDocument2.
Here are the steps to sink events for the currently loaded document:
The procedure to get the tag (and its attributes) "below" the mouse can be defined as:
var
htmlDoc : IHTMLDocument2;
...
procedure TForm1.Document_OnMouseOver;
var
element : IHTMLElement;
begin
if htmlDoc = nil then Exit;
element := htmlDoc.parentWindow.event.srcElement;
elementInfo.Clear;
if LowerCase(element.tagName) = 'a' then
begin
ShowMessage('Link, HREF : ' + element.getAttribute('href',0)]) ;
end
else if LowerCase(element.tagName) = 'img' then
begin
ShowMessage('IMAGE, SRC : ' + element.getAttribute('src',0)]) ;
end
else
begin
elementInfo.Lines.Add(Format('TAG : %s',[element.tagName])) ;
end;
end; (*Document_OnMouseOver*)
As explained above, we attach to the onmousemove event of a document in the OnDocumentComplete event of a TWebBrowser:
procedure TForm1.WebBrowser1DocumentComplete( ASender: TObject;
const pDisp: IDispatch;
var URL: OleVariant) ;
begin
if Assigned(WebBrowser1.Document) then
begin
htmlDoc := WebBrowser1.Document as IHTMLDocument2;
htmlDoc.onmouseover := (TEventObject.Create(Document_OnMouseOver) as IDispatch) ;
end;
end; (*WebBrowser1DocumentComplete*)
And this is where the problems arise! As you might guess the "onmousemove" event is *not* a usual event - as are those we are used to work with in Delphi.
The "onmousemove" expects a pointer to a variable of type VARIANT of type VT_DISPATCH that receives the IDispatch interface of an object with a default method that is invoked when the event occurs.
In order to attach a Delphi procedure to "onmousemove" you need to create a wrapper that implements IDispatch and raises your event in its Invoke method.
Here's the TEventObject interface:
TEventObject = class(TInterfacedObject, IDispatch)
private
FOnEvent: TObjectProcedure;
protected
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
public
constructor Create(const OnEvent: TObjectProcedure) ;
property OnEvent: TObjectProcedure read FOnEvent write FOnEvent;
end;