Entw.: IE-Programmierung (1)

Der Internet Exploxer vom Windows-Betriebssystem lässt sich direkt in einer Client-Applikation einbinden und programmieren. Im folgenden Artikel werden dazu einige Programmiertechniken gezeigt, mit denen man Web-Seiten automatisch auslesen und auswerten kann.
Es handelt sich hier um den 1. Teil einer Artikelserie.

Verwendete Unit's

Generell sind diese Unit's einzubinden. Sie enthalten alle notwendigen Typen und Deklarationen:

SysUtils

Classes

SHDocVw

MSHTML

Forms

Aufruf einer Web-Seite

Mit folgenden Aufruf wird eine Web-Seite programmiertechnisch aufgerufen:

var l_oleFlags: OLEVariant;

...

l_oleFlags := NavNoHistory or NavNoReadFromCache or

              NavNoWriteToCache or NavAllowAutosearch;

aWebBrowser.Navigate2(WideString(aURL), l_oleFlags);

Abzufangene Events

Diese Events sind unbedingt abzufangen und zu behandeln:

onBeforeNavigate2

onDocumentComplete

onNavigateError

Hier eine meiner Implementierungen als Beispiel:

procedure TMainForm.WebBrowserBeforeNavigate2(ASender: TObject;

    const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,

    Headers: OleVariant; var Cancel: WordBool);

begin

 uGlobal.g_oHtmlDoc2 := nil;

end;

 

procedure TMainForm.WebBrowserDocumentComplete(ASender: TObject;

   const pDisp: IDispatch; const URL: OleVariant);

begin

 uGlobal.g_iBrowserStatus := 0;

 if Assigned(WebBrowser.Document) then begin

   uGlobal.g_oHtmlDoc2 := WebBrowser.Document as IHTMLDocument2;

   uGlobal.g_oHtmlDoc2.DesignMode := 'Off';

 end;

end;

 

procedure TMainForm.WebBrowserNavigateError(ASender: TObject;

   const pDisp: IDispatch; const URL, Frame, StatusCode: OleVariant;

   var Cancel: WordBool);

begin

 uGlobal.g_iBrowserStatus := StatusCode;

 Cancel := True;

end;

Warten bis eine Web-Seite aufgebaut ist

Um eine Web-Seite auszuwerten und da der Aufbau einer HTML-Seite asynchron abläuft, muss abgewartet werden, bis die Web-Seite aufgebaut ist.

procedure WaitForPage(const aWebBrowser: TWebBrowser);

begin

 while aWebBrowser.ReadyState < READYSTATE_INTERACTIVE do begin

   Application.ProcessMessages;

   Sleep(200);

 end;

end;

Web-Seite als HTML-Element

Benötigt man die gesamte Web-Seite als HTML-Element, so kann folgende Prozedur zur Ermittlung verwendet werden:

function GetFullHTMLElement(const aWebBrowser: TWebBrowser):

              IHTMLElement;

var

 l_oHTMLElement: IHTMLElement;

begin

 Result := Nil;

 if Assigned(aWebBrowser.Document) then begin

   l_oHTMLElement := (aWebBrowser.Document as IHTMLDocument2).body;

   while l_oHTMLElement.parentElement <> nil do begin

     l_oHTMLElement := l_oHTMLElement.parentElement;

   end;

   Result := l_oHTMLElement;

 end;

end;

Attribut eines DOM-Knotens

Folgende Prozedur liefert zu einem DOM-Knoten (Document Object Model) ein gesuchtes Attribut spezifiziert durch seinem Namen:

function GetAttributeByName(aElement: IHTMLDomNode;

           const aAttrName: String;

           var aAtt: IHTMLDOMAttribute2): Boolean;

var

 l_lstCollec: IHTMLAttributeCollection;

 l_oAtt   : IHTMLDOMAttribute2;

 i        : Integer;

 l_sName  : String;

begin

 Result := False;

 l_lstCollec := aElement.attributes as IHTMLAttributeCollection;

 if Assigned(l_lstCollec) then begin

   l_sName := UpperCase(aAttrName);

   for i := 0 to l_lstCollec.length - 1 do begin

     l_oAtt := l_lstCollec.item(i) as IHTMLDomAttribute2;

     if UpperCase(l_oAtt.name) = l_sName then begin

       aAtt := l_oAtt;

       Result := True;

       break;

     end;

   end;

 end;

end;

Beispiel für die Verwendung der Prozedur:

var

 l_oHTMLDomNode: IHTMLDomNode;

 l_oAtt: IHTMLDOMAttribute2;

begin

 l_oHTMLDomNode := ((aWebBrowser.Document as IHTMLDocument2).body as

       IHTMLDocument3).getElementById('XYZ') as IHTMLDomNode;

 if Assigned(l_oHTMLDomNode) then begin

   if GetAttributeByName(l_oHTMLDomNode,'VALUE',l_oAtt) then begin

      ...

   end;

 end;

end;