Ottieni l'URL di un collegamento ipertestuale quando il mouse si sposta su un documento TWebBrowser

Il componente TWebBrowser Delphi fornisce l'accesso alla funzionalità del browser Web dalle applicazioni Delphi.

Nella maggior parte dei casi si utilizza TWebBrowser per visualizzare documenti HTML all'utente, creando così la propria versione del browser Web (Internet Explorer). Si noti che TWebBrowser può anche visualizzare documenti Word, ad esempio.

Una caratteristica molto utile di un browser è la visualizzazione delle informazioni sui collegamenti, ad esempio, nella barra di stato, quando il mouse passa sopra un collegamento in un documento.

TWebBrowser non espone un evento come "OnMouseMove". Anche se un evento del genere esistesse, verrebbe generato per il componente TWebBrowser - NON per il documento visualizzato all'interno di TWebBrowser.

Per fornire tali informazioni (e molto altro, come vedrai tra poco) nell'applicazione Delphi utilizzando il componente TWebBrowser, una tecnica chiamata "affondamento degli eventi"deve essere implementato.

Lavandino eventi WebBrowser

Per accedere a una pagina Web utilizzando il componente TWebBrowser, si chiama Navigare metodo. Il Documento la proprietà di TWebBrowser restituisce un IHTMLDocument2 valore (per documenti web). Questa interfaccia viene utilizzata per recuperare informazioni su un documento, esaminare e modificare gli elementi HTML e il testo all'interno del documento ed elaborare gli eventi correlati.

Per ottenere l'attributo "href" (link) di un tag "a" all'interno di un documento, mentre il mouse passa sopra un documento, è necessario reagire all'evento "onmousemove" di IHTMLDocument2.

Ecco i passaggi per affondare gli eventi per il documento attualmente caricato:

  1. Affondare gli eventi del controllo WebBrowser in DocumentComplete evento generato da TWebBrowser. Questo evento viene generato quando il documento è completamente caricato nel browser Web.
  2. All'interno di DocumentComplete, recupera l'oggetto documento di WebBrowser e affonda l'interfaccia HtmlDocumentEvents.
  3. Gestisci l'evento che ti interessa.
  4. Cancella il lavandino in BeforeNavigate2 - cioè quando il nuovo documento viene caricato nel browser Web.

Documento HTML OnMouseMove

Dato che siamo interessati all'attributo HREF di un elemento A - al fine di mostrare l'URL di un link su cui si trova il mouse, affonderemo l'evento "onmousemove".

La procedura per ottenere il tag (e i suoi attributi) "sotto" il mouse può essere definita come:

 var   htmlDoc: IHTMLDocument2; ... procedura TForm1.Document_OnMouseOver; var    elemento: IHTMLElement; inizio    Se htmlDoc = zero poi Uscita; element: = htmlDoc.parentWindow.event.srcElement; elementInfo.Clear;    Se LowerCase (element.tagName) = 'a' allora    inizio      ShowMessage ('Link, HREF:' + element.getAttribute ('href', 0)]);    fine    altro Se LowerCase (element.tagName) = 'img' poi    inizio      ShowMessage ('IMAGE, SRC:' + element.getAttribute ('src', 0)]);    fine    altro    inizio      elementInfo.Lines.Add (Format ('TAG:% s', [element.tagName]));    fine; fine; (* Document_onmouseover *) 

Come spiegato sopra, alleghiamo l'evento onmousemove di un documento nell'evento OnDocumentComplete di un TWebBrowser:

 procedura TForm1.WebBrowser1DocumentComplete (ASender: TObject; const pDisp: IDispatch; var URL: OleVariant); inizio    Se Assegnato (WebBrowser1.Document) poi    inizio      htmlDoc: = WebBrowser1.Document come IHTMLDocument2; htmlDoc.onmouseover: = (TEventObject.Create (Document_OnMouseOver) come IDispatch);    fine; fine; (* WebBrowser1DocumentComplete *) 

Ed è qui che sorgono i problemi! Come puoi immaginare l'evento "onmousemove" non è * un * un evento normale - come lo sono quelli con cui siamo abituati a lavorare in Delphi.

"Onmousemove" prevede un puntatore a una variabile di tipo VARIANT di tipo VT_DISPATCH che riceve l'interfaccia IDispatch di un oggetto con un metodo predefinito che viene richiamato quando si verifica l'evento.

Per allegare una procedura Delphi a "onmousemove" devi creare un wrapper che implementa IDispatch e genera il tuo evento nel suo metodo Invoke.

Ecco l'interfaccia di TEventObject:

 TEventObject = classe(TInterfacedObject, IDispatch) privato    FOnEvent: TObjectProcedure; protetta    funzione GetTypeInfoCount (su Conteggio: intero): HResult; stdcall;    funzione GetTypeInfo (Index, LocaleID: Integer; su TypeInfo): HResult; stdcall;    funzione GetIDsOfNames (const IID: TGUID; Nomi: puntatore; NameCount, LocaleID: Integer; DispIDs: Puntatore): HResult; stdcall;    funzione Invoke (DispID: Integer; const IID: TGUID; LocaleID: intero; Bandiere: Word; var Parametri; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; pubblico    costruttore Creare(const OnEvent: TObjectProcedure);    proprietà OnEvent: TObjectProcedure leggere FOnEvent Scrivi FOnEvent;    fine; 

Ecco come implementare il sink di evento per un documento visualizzato dal componente TWebBrowser e ottenere le informazioni di un elemento HTML sotto il mouse.

Esempio di affondamento di eventi del documento TWebBrowser

Scarica

Rilasciare un TWebBrowser ("WebBrowser1") su un modulo ("Form1"). Aggiungi un TMemo ("elementInfo") ...

unità Unità 1;
interfaccia
usi
   Windows, Messaggi, SysUtils, Varianti, Classi, Grafica, Controlli, Moduli,
   Finestre di dialogo, OleCtrls, SHDocVw, MSHTML, ActiveX, StdCtrls;
genere
   TObjectProcedure = procedura di oggetto;
   TEventObject = classe(TInterfacedObject, IDispatch)
   privato
     FOnEvent: TObjectProcedure;
   protetta
     funzione GetTypeInfoCount (out Count: Integer): HResult; stdcall;
     funzione GetTypeInfo (Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
     funzione GetIDsOfNames (const IID: TGUID; Nomi: puntatore; NameCount, LocaleID: Integer; DispIDs: Puntatore): HResult; stdcall;
     funzione Invoke (DispID: Integer; const IID: TGUID; LocaleID: intero; Bandiere: Word; var Parametri; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
   pubblico
     costruttore Creare(const OnEvent: TObjectProcedure);
     proprietà OnEvent: TObjectProcedure leggi FOnEvent scrivi FOnEvent;
   fine;
   TForm1 = classe(TForm)
     WebBrowser1: TWebBrowser;
     elementInfo: TMemo;
     procedura WebBrowser1BeforeNavigate2 (ASender: TObject; const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData, Header: OleVariant; var Annulla: WordBool);
     procedura WebBrowser1DocumentComplete (ASender: TObject; const pDisp: IDispatch; var URL: OleVariant);
     procedura FormCreate (Mittente: TObject);
   privato
     procedura document_onmouseover;
   pubblico
     Pubblico dichiarazioni
   fine;
var
   Form1: TForm1;
   htmlDoc: IHTMLDocument2;
implementazione
$ R * .dfm
procedura TForm1.Document_OnMouseOver;
var
   elemento: IHTMLElement;
inizio
   Se htmlDoc = zero poi Uscita;
   element: = htmlDoc.parentWindow.event.srcElement;
   elementInfo.Clear;
   Se LowerCase (element.tagName) = 'a' poi
   inizio
     elementInfo.Lines.Add ('LINK info ...');
     elementInfo.Lines.Add (Format ('HREF:% s', [element.getAttribute ('href', 0)]));
   fine
   altro Se LowerCase (element.tagName) = 'img' poi
   inizio
     elementInfo.Lines.Add ('Informazioni IMMAGINE ...');
     elementInfo.Lines.Add (Format ('SRC:% s', [element.getAttribute ('src', 0)]));
   fine
   altro
   inizio
     elementInfo.Lines.Add (Format ('TAG:% s', [element.tagName]));
   fine;
fine; (* Document_onmouseover *)
procedura TForm1.FormCreate (Mittente: TObject);
inizio
   WebBrowser1.Navigate ('http://delphi.about.com');
   elementInfo.Clear;
   elementInfo.Lines.Add ('Sposta il mouse sul documento ...');
fine; (* FormCreate *)
procedura TForm1.WebBrowser1BeforeNavigate2 (ASender: TObject; const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData, Header: OleVariant; var Annulla: WordBool);
inizio
   htmlDoc: = zero;
fine; (* WebBrowser1BeforeNavigate2 *)
procedura TForm1.WebBrowser1DocumentComplete (ASender: TObject; const pDisp: IDispatch; var URL: OleVariant);
inizio
   Se Assegnato (WebBrowser1.Document) poi
   inizio
     htmlDoc: = WebBrowser1.Document come IHTMLDocument2;
     htmlDoc.onmouseover: = (TEventObject.Create (Document_OnMouseOver) come IDispatch);
   fine;
fine; (* WebBrowser1DocumentComplete *)
TEventObject
costruttore TEventObject.Create (const OnEvent: TObjectProcedure);
inizio
   ereditato Creare;
   FOnEvent: = OnEvent;
fine;
funzione TEventObject.GetIDsOfNames (const IID: TGUID; Nomi: puntatore; NameCount, LocaleID: Integer; DispIDs: Puntatore): HResult;
inizio
   Risultato: = E_NOTIMPL;
fine;
funzione TEventObject.GetTypeInfo (Index, LocaleID: Integer; out TypeInfo): HResult;
inizio
   Risultato: = E_NOTIMPL;
fine;
funzione TEventObject.GetTypeInfoCount (out Count: Integer): HResult;
inizio
   Risultato: = E_NOTIMPL;
fine;
funzione TEventObject.Invoke (DispID: intero; const IID: TGUID; LocaleID: intero; Bandiere: Word; var Parametri; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
inizio
   Se (DispID = DISPID_VALUE) poi
   inizio
     Se Assegnato (FOnEvent) poi FOnEvent;
     Risultato: = S_OK;
   fine
   altro Risultato: = E_NOTIMPL;
fine;
fine.