Die Community zu .NET und Classic VB.
Menü

Tagmodell des Webbrowsers

 von 

Übersicht 

Wer über Erfahrungen mit HTML und Javascript (oder Jscript, VBScript) verfügt, wird feststellen, daß das Ansprechen von HTML-Objekten mit VB fast identisch ist. Oder anders herum, wer es in VB beherrscht wird auch keine Probleme mit Javascript haben.

Um die hier genannten Möglichkeiten nutzen zu können, müssen Sie die Komponente "Microsoft HTML Object Library" (mshtml.dll) zu Ihren Projekt hinzufügen. Weiterhin sollte man über gute Kenntnisse in HTML verfügen.

Mit freundlichen Grüßen
Thomas Mell

Unterschiede zwischen IE4 und IE5 [oder höher]  

Im IE4 kann man nur mittels des all-Objekts auf HTML-Objekte zugreifen. Da es sich bei diesem Objekt um eine microsofteigene Erfindung handelt, das W3-Konsortium hatte seinerzeit noch keine Spezifikationen für den Zugriff auf HTML-Objekte bereitgestellt, sollte es auch nur in Umgebungen benutzt werden, in denen der IE4 installiert ist.

Da mittlerweile die oben genannten Spezifikationen existieren, wurde ab der Version 5 das all-Objekt durch eine Sammlung von Methoden abgelöst. Damit diese Versionen abwärtskompatibel zum IE4 bleiben, existiert das all-Objekt in diesen weiter, sollte aber nicht mehr benutzt werden. Die neuen Methoden sind jedoch kein Bestandteil dieses, sondern werden in einem weiterführenden Artikel behandelt. Für Programme die verteilt werden, sollte man unbedingt mit dem all-Objekt arbeiten, da man nie sicher sein kann, daß bei jeden User der IE5 oder höher installiert ist.

In Umgebungen, die ab IE5 bereitsteht (z.B. Intranets) sollte man dagegen mit den "neuen" Methoden arbeiten, da diese bedeutend mächtiger und leichter zu handhaben sind.

Zugriff auf Formulare  

Sehr häufig wird der Wunsch geäußert auf Formulare und deren Elemente (Textfelder, Radiobuttons, Checkboxen, Popup-Menüs...) zuzugreifen, bzw. diese auszulesen oder zu füllen/setzen. Aus diesem Grund existieren im IE (egal welche Version) 3 Objekte, die nur für die Behandlung von Formularen bereitstehen - Forms , Elements und Options . Natürlich kann man auch mit dem (weiter unten erklärten) all-Objekt und der DOM-Syntax auf Formulare und deren Elemente zugreifen, das wäre aber mit Kanonen auf Spatzen geschossen.

Eine umfangreiche Erklärung dieser Objekte und deren Methoden/Eigenschaften würde den Rahmen dieses Artikel sprengen (dazu wird es einen eigenen Artikel geben). Ich werde jedoch die am häufigsten vorkommenden Anwendungen darstellen.

Als erstes wird beschrieben wie auf ein Formular zugegriffen wird (nicht auf die darin enthalten Elemente, dazu kommen wir später). Formulare liegen im IE als Objekte vor, und zwar vom Typ Forms .

Dieses Objekt besitzt u.a. die Eigenschaften:

Eigenschaft Beschreibung
action Die URL, zu welcher das Formular geschickt werden soll.
name Der Name des Formular, welcher im Name-Attribut steht.
target Gibt den Namen des Frame an, in welchem eine Antwortseite des Server angezeigt werden soll.
length Anzahl der Formulare im Dokument.

Tabelle 1

Da ein HTML-Dokument mehrere Formulare enthalten kann, könnte man zunächst feststellen um wieviele es sich dabei handelt, folgendes erledigt dies für uns:

WebBrowser1.Document.Forms.length

Listing 1

Da gleichnamige Tags [hier das <Form> Tag] als Objektarray [ich nenne es einfach mal so] vorliegen, kann man diese auch wie ein Array ansprechen:

WebBrowser1.Document.Forms(1)

Listing 2

gibt uns das zweite <Form> Tag als Objekt zurück.

Sollte ein Formular über ein name-Attribut verfügen, kann dieses auch über:

WebBrowser1.Document.Forms("formularName")

Listing 3

als Objekt erhalten werden.

Nun steht nichts im Wege die Eigenschaften des form-Objekt auszulesen oder neu zu beschreiben:

x = WebBrowser1.Document.Forms("formularName").action

Listing 4

gibt die Absende-URL zurück. Möchten Sie diese ändern ?

WebBrowser1.Document.Forms(1).action = "neueURL"

Listing 5

Wo Objekte sind, da sind nicht nur Eigenschaften sondern auch Methoden (meistens). Da macht auch das forms -Objekt keine Ausnahme:

Methode Beschreibung
reset Löscht alle Formularinhalte.
submit Schickt das Formular ab.

Tabelle 2

Ein Formular abzuschicken ist somit ein Kinderspiel:

WebBrowser1.Document.Forms("meinFormular").submit

Listing 6

In VB existieren für alle möglichen Tags eigene Objekttypen. Hier wäre dies HTMLFormElement

Dim myForm As HTMLFormElement

    Set myForm = WebBrowser1.Document.Forms(0)
    myForm.action = "neueURL"

Listing 7

In myForm befindet sich nun das erste Formular als Objekt und es können alle Methoden und Eigenschaften angewandt werden. Diese finden Sie im Objektkatalog.

Wie von VB gewohnt, existieren auch in HTML-Dokumenten Ereignisse (Events). Diese Events können ohne großen Aufwand an VB "weitergeleitet" werden. Um bei Formularen zu bleiben, werde ich zeigen wie man in VB ein Ereignis auslöst, wenn ein Formular z.B. mit einen Mausklick auf dem Submit-Button abgeschickt wird.

Option Explicit

Dim WithEvents myForm As HTMLFormElement

Private Sub Form_Load()
  WebBrowser1.Navigate2 "formular.html"
End Sub

Private Sub WebBrowser1_DocumentComplete _
(ByVal pDisp As Object, URL As Variant)
  Set myForm = WebBrowser1.Document.Forms("meinFormular")
End Sub

Private Function myForm_onsubmit() As Boolean
  MsgBox "Wer wagt es mein Formular abzuschicken ?"
End Function

Listing 8

Führen Sie bitte dieses Beispiel einmal aus - fällt ihnen etwas auf ? Die Messagbox erscheint, Sie klicken auf "ok" und was passiert ? Nichts, rein gar nichts - das Formular wird nicht abgeschickt. Warum?

Das liegt darin begründet, daß beim Auslösen dieses Events dieses zwar ausgeführt wird, aber nicht die Aktion welches das Event verursacht hat [hier der Klick auf den Submit-Button]. Das Event erwartet nämlich einen Rückgabewert, ob die Aktion letztendlich ausgeführt werden soll oder nicht.

Aus diesem Grund werden bei HTML-Events häufig Funktionen benutzt [siehe oben - myForm_onsubmit]. Da wir keinen Rückgabewert angegeben haben, wird defaultmäßig "False" benutzt und das Formular nicht abgeschickt.

Fügen Sie nun bitte die Zeile:

myForm_onsubmit = True

Listing 9

unterhalb der MsgBox-Zeile ein und schon macht sich das Formular auf die Socken. Alle weiteren Events des Objektes finden Sie [wo sonst] im Objektkatalog.

Der IE stellt ein "richtiges" Event-Objekt zur Verfügung, worüber jede Aktion des User abgefangen werden kann [wie in VB, aber bedeutend mächtiger] Dieses Objekt werde ich in einen weiteren Artikel vorstellen.

Zugriff auf Formularelemente  

Der Zugriff auf Formularelemente stellt sich genau so trivial dar wie der auf Formulare. Wie sollte es anders sein, für die Elemente existiert ein Objekt namens Elements . Wie im Forms -Objekt kann auch im Elements -Objekt ein Element über einen Index oder dessen Name [steht im Name-Attribut ] erreicht werden:

WebBrowser1.Document.Forms(0).elements(0)
WebBrowser1.Document.Forms(0).elements("MyFormElement")
WebBrowser1.Document.Forms("MyForm").elements(8)
WebBrowser1.Document.Forms("MyForm").elements("MyFormElement")

Listing 10

Um was für ein Element handelt es sich aber bei dem entsprechenden Objekt ? Dafür gibt es die Eigenschaft Type :

WebBrowser1.Document.Forms(0).elements(0).Type

Listing 11

Mögliche Rückgabewerte:

Wert Beschreibung
Text Text-Eingabefeld
Password Passwortfeld
Textarea Mehrzeiliges Text-Eingabefeld
Submit Abschicken Button
Reset Reset Button
Button Button ohne Funktion [kann aber Events auslösen]
Checkbox Checkbox
Radio Radiobuttons
Select-one select-one
select-multiple select-multiple
File Upload - Element
Hidden Unsichtbares Feld [kann nur Text speichern]

Tabelle 3

Jetzt müssen wir nur noch wissen wie die Werte der Elemente gelesen bzw. geändert werden können. Da dies je nach Elementetyp sehr verschieden realisiert wird, werden diese einzeln beschrieben.

  • text, password, textarea, hidden
    <input type="text, password, textarea, hidden" name="Name" value="Wert">

    Diese Elemente können nur Text enthalten.

    x = WebBrowser1.Document.Forms(0).elements(0).value
    WebBrowser1.Document.Forms(0).elements(0).value = "neuer Wert"

    Listing 12

  • checkbox, radiobutton
    <input type="submit, reset, button" name="meinName" value="ButtonText">

    Da es sich bei diesen Elementen um Buttons handelt, wird der Beschriftungstext gelesen / geändert. Die Syntax ist identisch mit dem obigen Punkt.

  • text, password, textarea, hidden
    <input type="checkbox" name="meinName" value="meinWert">

    Listing 13: HTML Code für Checkbox

    <input type="radio" name="meinName"     value="meinWert-1">
    <input type="radio" name="gleicherName" value="meinWert-2">
    <input type="radio" name="gleicherName" value="meinWert-3">

    Listing 14: HTML Code für Radiobuttons

    Bei diesen Buttons gibt es nur zwei Zustände - True oder False

    x = WebBrowser1.Document.Forms(0).elements(0).Checked

    Listing 15: Gibt True oder False zurück

    WebBrowser1.Document.Forms(0).elements(0).Checked = True

    Listing 16: Aktiviert einen Button

    x = WebBrowser1.Document.Forms(0).elements(0).Value

    Listing 17: Liefert den Inhalt des value-Attributs zurück. Dieser Wert wird verschickt wenn der Button aktiv ist

  • select-one

    Dieses Element besteht nicht nur aus einem Tag, sondern aus mehreren. Deswegen unterscheidet es sich grundlegend von allen anderen Formularelementen. Eingeleitet wird es mit dem <select> Tag und jeder Auswahlpunkt besteht aus einem <option> Tag.

    <select name="meinMenue">
      <option value="FF0000">Rot</option>
      <option value="00FF00">Grün</option>
      <option value="0000FF">Blau</option>
    </select>

    Im elements Objekt befindet sich aber nur das select-Tag als Objekt. Für die option-Tags existiert [wie wäre es auch anders zu erwarten] das options Objekt. Jetzt wird es etwas komplizierter, da mehrere Möglichkeiten existieren auf diesen Wulst von Objekten zuzugreifen. Fangen wir mal mit einem einfachen Beispiel an:

    Mit

    x = WebBrowser1.Document.Forms(0).elements(0).length

    Listing 18

    ermitteln wir die Anzahl der Auswahlmöglichkeiten und

    x = WebBrowser1.Document.Forms(0).elements(0).selectedIndex

    Listing 19

    oder

    x = WebBrowser1.Document.Forms(0).elements("Menue").selectedIndex

    Listing 20

    gibt den Index der aktiven Auswahl zurück.

    Einen Menüpunkt selektieren können wir mit

    WebBrowser1.Document.Forms(0).elements("Menue").selectedIndex = 2

    Listing 21

    Um auf die Eigenschaften eines Menüpunktes zuzugreifen, bringen wir nun das options Objekt ins Spiel. Achtung: Das options Objekt kann NUR mit einem Index belegt werden. Im Gegensatz zum forms und elements Objekt darf dort nicht der Name eines <option> Tag benutzt werden.

    WebBrowser1.Document.Forms_
    (0).elements("Menue").options(2).selected = True

    Listing 22

    bewirkt genau das Selbe wie im Beispiel zuvor.

    x = WebBrowser1.Document.Forms(0).elements("Menue").options(1).value

    Listing 23

    Liefert uns den value-Wert und

    x = WebBrowser1.Document.Forms(0).elements("Menue").options(1).Text

    Listing 24

    den sichtbaren Text des 2. Menüpunktes.

    Wie Sie sehen, kann nur ermittelt werden, welcher Menüpunkt aktiv ist, bzw. den Wert eines bestimmten Menüpunktes. Um den Wert [oder Text] des aktiven Menüpunktes zu erfahren, muß man beide Möglichkeiten kombinieren:

    WebBrowser1.Document.Forms(0).elements(0).Options _
       (WebBrowser1.Document.Forms(0).elements(0).selectedIndex).Value

    Listing 25

    Und zu guter letzt erkläre ich noch wie Menüpunkte entfernt bzw. hinzugefügt werden. Hierfür müssen wir zwischen dem IE4 und IE5 oder höher unterscheiden.

Das Entfernen eines Menüpunktes

IE4

Beim IE4 existiert keine Möglichkeit Menüpunkte zu entfernen. Allerdings kann man mit der length Eigenschaft die Liste verkürzen:

WebBrowser1.Document.Forms(0).elements("Menue").length = 2

Listing 26

Waren zuvor z.B. 5 Menüpunkte vorhanden, dann würde nun nur noch die ersten 2 angezeigt werden.

IE5 oder höher

Im Gegensatz zum IE4 bereitet es im IE5 oder höher keinerlei Problem einzelne Menüpunkte zu entfernen:

WebBrowser1.Document.Forms(0).elements("Menue").removeChild _
   (WebBrowser1.Document.Forms(0).elements("meinMenue").children(4))

Listing 27

oder etwas leserlicher:

Dim optio As HTMLOptionElement

  Set optio = WebBrowser1.Document.Forms(0).elements("meinMenue")
  optio.removeChild (optio.children(4))

Listing 28

Da diese Syntax zum DOM-Wortschatz gehört, möchte ich darauf nicht näher eingehen [auch dazu werde ich noch einen eigenen Artikel verfassen]. In diesem Beispiel brauchen Sie nur zu wissen das der Index des zu löschenden Menüpunktes in der Methode children angegeben wird [hier der 5. Eintrag].

Hinzufügen von Menüpunkten

IE4

Auch hier können wir neue Elemente nur am Ende der Liste anfügen:

Als erstes ermitteln wir die Anzahl der Einträge...

x = WebBrowser1.Document.Forms(0).elements(0).length

Listing 29

....dann erhöhen wir die Anzahl um eins....

WebBrowser1.Document.Forms(0).elements(0).length = x + 1

Listing 30

....und nun den Text angeben.....

WebBrowser1.Document.Forms(0).elements(0).Options(x).Text = "Neuer Eintrag"

Listing 31

....und zu guter letzt einen Wert verpassen.

WebBrowser1.Document.Forms(0).elements(0).Options(x).Value = "Neuer Wert"

Listing 32

IE5 oder höher

Wie nicht anders zu erwarten, kann im IE5 oder höher an jeder Stelle der Liste ein neuer Eintrag hinzugefügt werden:

Eine Objektvariable vom Typ IHTMLOptionElement anlegen.......

Dim optio As IHTMLOptionElement

Listing 33

.... dann ein neues OPTION-Objekt erzeugen...

Set optio = WebBrowser1.Document.createElement("OPTION")

Listing 34

....dem neuen Objekt einen "Text”.....

optio.Text = "Neuer Eintrag"

Listing 35

....und einen "Wert” geben...

optio.Value = "Neuer Wert"

Listing 36

....und zum Schluß ins Menü einfügen.

WebBrowser1.Document.Forms(0).elements("meinMenue").Add optio, 4

Listing 37

In der letzten Zeile wird die Position angegeben, an welcher der neue Eintrag eingefügt wird [4.]

select-multiple

Dieses Element ist weitgehend identisch mit dem select-one - PopMenü. Es unterscheidet sich lediglich durch die Möglichkeit mehrere Menüpunkte zu selektieren. Das Aktivieren eines Menüpunktes wird genau so realisiert wie beim select-one - PopMenü.

WebBrowser1.Document.Forms(0).elements(0).Options(2).Selected = True
WebBrowser1.Document.Forms(0).elements(0).Options(4).Selected = True

Listing 38

Selektiert den 3. und 5. Menüpunkt.

Um festzustellen welche Menüpunkte aktiv sind, müssen wir alle in einer Schleife überprüfen:

Dim n

  For Each n In WebBrowser1.Document.Forms(0).elements(0).Options
    If n.Selected Then Debug.Print n.Value
  Next n

Listing 39

Dieses Beispiel schreibt alle Werte der aktiven Menüpunkte ins Debugfenster.

Das all-Objekt  

Mit Hilfe des all-Objekts hat man Zugriff auf alle Tags und Inhalte einer HTML-Datei. Die meisten Attribute kann man lesen und ändern. Methoden des all-Objekts erlauben unter anderem das Einfügen oder Entfernen von HTML-Tags, Attributen und lesbaren Text. Auf diese Weise ist der dynamische Zugriff auf alle Bestandteile einer HTML-Datei möglich. Von "Hause" aus stellt das all-Objekt eine Liste aller Tags bereit, welche wie ein Array angesprochen werden können. Jedes Tag steht innerhalb dieser Liste als Objekt zur Verfügung auf welche wiederum eine Unmenge Methoden und Eigenschaften angewandt werden können.

WebBrowser1.Document.All(0).outerHTML

Listing 40

Hiermit greifen wir auf das erste (Index 0) Tag im Dokument zu, welches immer das <HTML> Tag darstellt. Mit der Methode outerHTML erhalten wir den gesamten Inhalt dieses Tags einschließlich sich selbst, also z.B.:

<html>
  <body>
    <p>Hallo Welt</p>
  </body>
</html>

Listing 41

Somit erhalten wir den gesamten HTML-Quelltext des Dokumentes.

Dagegen erhält man mit der Methode innerHTML nur den Inhalt eines Tags. In unseren Fall also:

<code>
  <body>
    <p>Hallo Welt</p>
  </body>
</code>

Listing 42

Weiterhin existiert noch die Methode innerText, womit man den lesbaren [gleich dem im Browser sichtbaren] Text erhält:

Hallo Welt

Und zu guter letzt kann man mit all.length die Anzahl aller Tags ermitteln:

3

Da man eigentlich nur beim <HTML> Tag den Index kennt [immer 0] ist das Ansprechen anderer Tags reine Glückssache, es sei denn es handelt sich um selbst geschriebene Dokumente und man macht sich die Mühe die Indexe der benötigten Tags abzuzählen. Aber zum Glück gibt es dafür noch weitere Methoden. Da wäre z.B. tagName:

Dim n

  For Each n In WebBrowser1.Document.All
    Debug.Print n.tagName
  Next n

Listing 43

Dies gibt alle Tagnamen aus.

HTML
BODY
P

So kann man zumindest schon mal nach bestimmten Tags suchen. Da es dabei doch recht mühselig ist z.B. nach dem x-ten <P> Tag zu suchen, können wir uns das Leben mit der Methode tags("TAG") erleichtern. Diese Methode stellt uns (wie das all-Objekt) eine Liste von Tags zur Verfügung, aber nur von einer "Sorte”:

WebBrowser1.Document.All.tags("A").length

Listing 44

Gibt uns die Anzahl aller <A> Tags zurück. Nun kann man wiederum mit

WebBrowser1.Document.All.tags("A")(5).innerText

Listing 45

Den Textinhalt des 6. <A> Tag auslesen.

Genau so einfach kann man auch auf die Attribute eines Tag zugreifen. Sie möchten die Hintergrundfarbe der Seite wissen ? Kein Problem:

WebBrowser1.Document.All.tags("BODY")(0).bgColor

Listing 46

Oder aber das Hintergrundbild ?

WebBrowser1.Document.All.tags("BODY")(0).background

Listing 47

Darf es die externallinkadresse des 9. <A> Tag sein ?

WebBrowser1.Document.All.tags("A")(8).href

Listing 48

Der Filename des 3. Bildes?

WebBrowser1.Document.All.tags("IMG")(2).src

Listing 49

Oder die Breite ?

WebBrowser1.Document.All.tags("IMG")(2).Width

Listing 50

Usw....

Das ist zwar alles schön und gut, aber wie soll man auf ein Bild zugreifen von dem man nicht den Index kennt ? Bei "fremden” Seiten hat man da keine Chance, sehrwohl aber bei eigenen. Dafür muß man in den Tags welche man ansprechen möchte das Attribut id schreiben:

<html>
  <body>
    <img id=”meinBild” src=”vollDasBild.gif”>
  </body>
</html>

Listing 51

Nun ist es ein leichtes das <img> Tag ohne Angabe eines Index anzusprechen:

WebBrowser1.Document.All.meinBild.src

Listing 52

Selbstverständlich kann man auch hier die oben gezeigten Methoden und Eigenschaften anwenden. Es existieren bei weitem noch mehr Methoden und Eigenschaften als hier dargestellt. Weitere Informationen darüber bekommt man bei Microsoft unter den im Anhang genannten URL`s.

Wie füge ich nun ein DIV-Element ein ?

Dim TestDiv As IHTMLDivElement
Set TestDiv = WebBrowser1.Document.createElement("DIV")
    With TestDiv
        .Id = "TESTID"
        .Style.display = "block"
        .Style.position = "absolute"
        .Style.Left = "0"
        .Style.Top = "0"
        .innerHTML="TEXT"
    End With
WebBrowser1.Document.body.appendChild TestDiv

Listing 53

Zum Abschluß zeige ich noch wie man ermitteln kann, das wievielte Tag im Dokument ein mit tags() oder all.id selektiertes Tag ist. Dies geschieht mit der Eigenschaft sourceIndex

WebBrowser1.Document.All.tags("INPUT")(2).sourceIndex

Listing 54

oder

WebBrowser1.Document.All.meinBild.sourceIndex

Listing 55

Zugriff auf Frames  

Ergänzung vom 24.11.2007 durch Philipp Burch:

Das WebBrowser-Steuerelement stellt bequeme Möglichkeiten bereit, auf die einzelnen Frames einer Website mit Framesets zuzugreifen. Die Anzahl vorhandener Frames kann mittels WebBrowser1.Document.frames.length ausgelesen werden. Ist diese Anzahl grösser als Null, ist für jeden Frame wiederum ein Document-Objekt vorhanden:
WebBrowser1.Document.frames(0).Document
Damit kann auch ganz einfach auf verschachtelte Frames zugegriffen werden, indem durch rekursive Aufrufe einer Funktion so tief gesucht wird, bis man ein Document-Objekt findet, welches keine weiteren Frames beinhaltet (Document.frames.length = 0).

Private Sub ReadFrames(Doc As HTMLDocument)
    If Doc.frames.length > 0 Then
        'Weitere Frames vorhanden
        Dim i As Long
        For i = 0 To Doc.frames.length - 1
            Call ReadFrames(Doc.frames(i).Document)
        Next i
    Else
        'Keine weiteren Frames vorhanden
        '-> Inhalt kann verwendet werden
        Call MsgBox("Frame: " & Doc.Title, vbInformation, "Frame")
    End If
End Sub

Listing 56: Auslesen von Frames

Beispielprojekt  

Projekt als Download [5600 Bytes]

externallinks zum Thema  

Formularelementetypen

Objekte

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.