![]() |
Webbrowser.OleObject mittels Vorfahren erreichen
Hallo Leute,
ich hoffe, ich kann meine Frage verständlich formulieren. Ich möchte auf ein Textfeld in einem html-Document zugreifen. Das geht ja so:
Delphi-Quellcode:
wb.OleObject.Document.All.Item('ItemName').Value := 'Test';
Nun habe ich das Problem, dass ich nicht direkt über das BrowserControl zugreife sondern den Container Components nach dem Element durchsuche. Und jetzt wirds kurz kompliziert. Warum nicht direkt. Ich benutze die TEmbeddedWb-Komponente. Binde ich EmbeddedWB in die uses ein, so bekomme ich eine Fehlermeldung des Compilers bei der Benutzung von Laufzeitbibliotheken. Das war so ne Sache mit zu vielen Pfaden, Zweigen? in der BPL-Nutzung. Ist schon ne' Zeit her, als ich mich darum gekümmert habe. Punkt ist, ich kann in der Unit EmbeddedWB nicht einbinden. Jetzt dachte ich, egal, OleObject sollte durch einen Vorfahren implementiert werden und hab in einer kleinen Testanwendung mal mit Code-Folding geschaut wo das denn ist. Der Aufruf geht direkt zu TOleControl.OleObjekt. Na, dachte mir nichts leichter als das, da haben wir ja die Vererbung incl. Typ-Konvertierung.
Delphi-Quellcode:
TOleControl(Components[i]).OleObject.Document.All.Item('ItemName').Value := 'Test';
sollte die Lösung sein. Nichts ist. Bis Item werden gültige Adressen angezeigt, dann ist Schluss. Exception mit Zugriff auf 0000. Ich denke mal, die Typkonvertierung ist hier falsch. Vielleicht wird OleObject auch durch ein Interface eingebunden. Bin bei der ganzen Sache aber leider nicht fitt. Kann mir einer einen Weg zeigen wie ich das hinbekomme? Das soll es aber nicht sein:
Delphi-Quellcode:
TEmbeddedWB(Components[i]).OleObject.Document.All.Item('ItemName').Value := 'Test';
Ich dank schon mal im Voraus, Gruß oki |
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Zitat:
Ist es ein Inputfield eines Webforms oder einfach nur ein HTML-Element mit einem gesetzen ID-Attribut. Zitat:
|
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Da ich nur einmal kurz mit der TEmbeddedWb-Komponente gearbeitet hatte, bin ich dafür sicher kein Experte.
Ich habe allerdings das Beispiel aus Interesse einmal getestet: Und bei mir war schon nach Document Schluß. Also liefert OleObject schon keinen Zeiger auf Document. Da OleObject eine Variante als Ergebnis liefert, wird anschießend versucht, über _DispInvoke in der Unit Variants einen Zeiger auf Document zu erhalten. Das geschieht durch den Aufruf von VarDispInvoke in der Unit ComObj. Innerhalb dieser Prozedur wird mit GetIDsOfNames die DispatchID von Document innerhalb des Objektes OleObject ermittelt (203). Das funktioniert auch - deshalb wird im Anschluß DispatchInvoke aufgerufen. Hier treten die Probleme auf: Mein Delphi-Compiler (Delphi2010) interpretiert meinen Untersuchungen zufolge den Aufruf von Document aus den RTTI als Methode (DISPATCH_METHOD). Dabei hatte ich mein Formular mit dem Schalter {$METHODINFO ON} compiliert. Document ist aber eine Eigenschaft des übergeordneten Objektes (genauer gesagt: Es ist selbst wieder ein COM-Objekt). Und hier scheint der Fehler aufzutreten: Document wird aufgerufen, statt einen Zeiger auf dieses Objekt zu ermitteln. Dieser wäre nämlich notwendig, um sich zum nächsten Objekt (All) "durchzufragen". Lange Rede, kurzer Sinn: So scheint das leider nicht zu funktionieren. Da ich bei meinem aktuellen Projekt ebenfalls auf einige Bugs innerhalb der Ole-Umsetzung gestoßen bin, habe ich das anders gelöst:
Delphi-Quellcode:
Habe ich gerade getestet - funktioniert. :thumb:
procedure SetProperty(WebBrowser: TWebBrowser; NodeName, PropertyName: String; Value: OleVariant);
var All, Node: OleVariant; begin //"All"-Objekt des Dokumentes ermitteln: All:=GetProp(WebBrowser.Document,'all'); //HTML-Element aus dem "All"-Objekt ermitteln: Node:=GetProp(All,NodeName); //Eigenschaft des HTML-Elementes setzen: SetProp(Node,PropertyName,Value); end; Die notwendigen Funktionen GetProp und SetProp habe ich aus der Unit BrowserTools im Downloadbereich der aktuellen ![]() |
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Hallo und guten Morgen.
Sorry, dass ich gestern nicht mehr antworten konnte, ist der Stress ausgebrochen. Shmia: Ich möchter auf ein Text-Eingabefeld zugreifen (input type Text). Grundsätzlich ist das für das aktuelle Problem wurscht, aber für alternative Wege vielleicht nicht. Zugriff auf ein Element Type button ist auch noch von nöten. by Thom: Erst mal Dank für deine Mühe. Vorweg, in einem kleinen Testprojekt klappt der Zugriff:
Delphi-Quellcode:
wb.OleObject.Document.All.Item('ItemName').Value := 'Test';
ohne Probleme. WB ist dabei natürlich TEmbeddedWB. Das Problem steckt da, dass ich über einen Vorfahren/anderen Weg zugreifen will/muss. Also ohne Einbindung des Packages/Unit EmbeddedWB. In deiner Funktion übergibst du einen Parameter vom Typ TWebBrowser. Ich denke mal, du gehst davon aus, dass ich dann sicher TEmbeddedWB benutzen muss und die beiden nicht "kompatibel" sind. Damit bin ich dann wieder da wo ich vorher war, ich muss die entsprechenden Units einbinden. Konkret in Bezug auf deine Funktion suche ich jetzt für die Übergabe einen Typ, der einem Vorfahren entspricht. Dabei gehe ich davon aus, dass sowohl TWebBrowser wie auch TEmbeddedWB nicht die Klassen sind, die OleObjekt und somit Dokument einbinden. Das erfolgt doch sicher im Rahmen der Vererbung viel früher. Da ich an keinen anderen Eigenschaften interessiert bin will ich einfach auf diesen Vorfahren casten und somit auf die Eigenschaft zugreigen. Mal ein einfaches Beispiel, ich habe ein Panel und will den Namen haben. In meiner Funktion will ich den Parameter in dem ich das Panel übergebe aber auch für andere Komponenten benutzen. So definiere ich den Parameter als TComponent. Stopfe ich da das Panel rein (TComponent(MyPanel)), so kann ich innerhalb der Funktion mittels AComponent.Name den Namen des übergebenen Panels erreichen. Ja, und das nun mit dem Browser und zugriff auf OleObject. Mein Versuch mit TOleControl ging in die Hose. Welcher Klassentyp ist der richtige? Gruß oki |
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo oki,
da hast Du natürlich Recht: Zitat:
Delphi-Quellcode:
Damit wäre es dann egal, ob das Dokument aus TWebBrowser.Document oder TEmbeddedWB.Document (bzw. TEmbeddedWB.OleObject.Document) stammt.
procedure SetProperty(Document: IDispatch; NodeName, PropertyName: String; Value: OleVariant);
var All, Node: OleVariant; begin //"All"-Objekt des Dokumentes ermitteln: All:=GetProp(Document,'all'); //HTML-Element aus dem "All"-Objekt ermitteln: Node:=GetProp(All,NodeName); //Eigenschaft des HTML-Elementes setzen: SetProp(Node,PropertyName,Value); end; Ist aber unwichtig: Ich habe das Ganze heute noch einmal - im Gegensatz zu gestern - in einem neuen Projekt ausprobiert. Da hatte ich das einfach in mein aktuelles Projekt "integriert". Und siehe da: Es funktioniert! Das ist schon recht interessant, wie da der Compiler im Hintergrund "herumzaubert", so dass es - abhängig von den Randbedingungen - mal funktioniert und mal nicht... Zu Deiner Frage: Du brauchst zum Zugriff auf das HTML-Element also nur - wie schon erwähnt - das Interface des Document-Objektes. Dabei ist es egal, ob es als IDispatch oder "verpackt" als (Ole-)Variant vorliegt. Damit der Compiler aber solchen Quelltext wie
Delphi-Quellcode:
akzeptiert, ist die Verwendung einer Variante besser. Schließlich generiert der Compiler hier den Code nur auf "gut Glück", da er noch nicht wissen kann, ob die Zeiger auch wirklich existieren. Erst zur Laufzeit "fragt" sich das Programm dann recht aufwändig (siehe mein erster Beitrag) von Objekt zu Objekt durch.
Document.Irgendwas.NochWasAnderes
Praktisch bedeutet das: Du mußt von der Unit, die die Browser-Komponente beherbergt, das Document-Interface an die Unit, von der aus Du auf die Browser-Komponente zugreifen möchtes, weiterreichen:
Delphi-Quellcode:
Von dort aus kannst Du dann ohne dem Wissen, aus welcher Browser-Komponente das Dokument stammt, darauf zugreifen:
procedure TForm1.FormCreate(Sender: TObject);
begin EmbeddedWB1.LoadFromFile('Test.html'); end; procedure TForm1.FormShow(Sender: TObject); begin Form2.Document:=EmbeddedWB1.Document; end;
Delphi-Quellcode:
Ich habe das Ganze mal als Zip-Datei angehängt.
procedure TForm2.Button1Click(Sender: TObject);
var Element: Variant; begin if VarIsType(Document,varDispatch) then begin Element:=Document.All.Item('Test'); if not VarIsClear(Element) then Element.InnerText:=Edit1.Text else ShowMessage('Element nicht gefunden'); end; end; |
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Zitat:
Ein Document kann ein oder mehrere "WebForms" enthalten. Ein Form enthält dann ein (oder mehrere) Input Items. Man kann dann z.B. mit einer Schleife über die Items und die Werte verändern. Hier ein Beispiel:
Delphi-Quellcode:
procedure FillWebForm(document:OleVariant);
var FormItem, Element : OleVariant; j : integer; itemtype, itemname : string; begin if document.forms.Length = then Exit; // keine WebForms vorhanden FormItem := document.forms.Item(0); // 1. Formular verwenden For j:= 0 to FormItem.Length-1 do begin Element := FormItem.Item(j); itemname := Element.Name; itemtype := UpperCase(Element.Type); if itemtype = 'TEXT' then begin maxlen := Element.MaxLength; Element.Value:= Copy('Hallo das ist ein Test', 1, maxlen); end else if itemtype = 'CHECKBOX' then begin // Checkbox zufällig setzen if system.Random > 0.5 then Element.Checked := True; end; // weitere Itemtypes sind BUTTON, CHECKBOX, SELECT-ONE, RADIO end; FormItem.Submit; // Webform absenden end; |
AW: Webbrowser.OleObject mittels Vorfahren erreichen
Hallo Leute,
es ist schon ein paar Tage her, aber ich bin an diesem Thema weiter gekommen. Es lag nicht an der Benutzung im speziellen sondern konkret an einer Stelle. folgender Code arbeitet ohne Probleme:
Delphi-Quellcode:
wb.OleObject.Document.All.Item('ItemName').Value := 'Test';
wb.OleObject.Document.All.Item('ItemName').Value := Edit1.Text; folgender nicht:
Delphi-Quellcode:
aber so:
NewText : String;
... NewText := 'Test'; wb.OleObject.Document.All.Item('ItemName').Value := NewText;
Delphi-Quellcode:
Das schien das ganze Problem gewesen zu sein. Ich denke mal, dass mein Problem erst darurch aufgetaucht ist, dass ich in meiner kleinen Testanwendung Edit1.Text zugewiesen habe und in meinem eigentlichen Code einen String. Für mich war das das gleiche und so habe ich den Unterschied in der Zuweisung gar nicht erst beachtet. Nach dem ich mich durch die Hilfe mittels IXMLDocument2 ... Item usw. gehangelt hatte viel mir die variante Parameterverwendung auf. Naja, nun klappts mit der Typkonvertierung ohne Probleme. Zusätzlich hat mich natürlich noch der Compiler aus der Bahn geworfen, da er dann auch immer schon für die Prüfung auf Document Adresse 0000 ausgeworfen hatte. So ist das halt im Leben.
NewText : String;
... NewText := 'Test'; wb.OleObject.Document.All.Item('ItemName').Value := Variant(NewText); Wollte auf jeden Fall noch die Lösung posten, damit der Nächste nicht leer da steht. Zusätzlich noch mal herzlichen Dank für die Code-Snippes zu testen. Gruß oki [edit] kurzer Nachtrag; das unter D2007; Gruß oki [/edit] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz