Visual Basic Tagmodell des Webbrowsers

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 undOptions . 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:
EigenschaftBeschreibung
actionDie URL, zu welcher das Formular geschickt werden soll.
nameDer Name des Formular, welcher im Name-Attribut steht.
targetGibt den Namen des Frame an, in welchem eine Antwortseite des Server angezeigt werden soll.
lengthAnzahl 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:
MethodeBeschreibung
resetLöscht alle Formularinhalte.
submitSchickt 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:
WertBeschreibung
TextText-Eingabefeld
PasswordPasswortfeld
TextareaMehrzeiliges Text-Eingabefeld
SubmitAbschicken Button
ResetReset Button
ButtonButton ohne Funktion [kann aber Events auslösen]
CheckboxCheckbox
RadioRadiobuttons
Select-oneselect-one
select-multipleselect-multiple
FileUpload - Element
HiddenUnsichtbares 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

SHARE

Oscar perez

Arquitecto especialista en gestion de proyectos si necesitas desarrollar algun proyecto en Bogota contactame en el 3006825874 o visita mi pagina en www.arquitectobogota.tk

  • Image
  • Image
  • Image
  • Image
  • Image
    Blogger Comment
    Facebook Comment

0 comentarios:

Publicar un comentario