Na fóru je pěkné pojednání o použití TWebBrowser.Document a mám svolení ho zde publikovat.
Na počátku všeho je reference interface (což je něco jako instance objektu akorát pro interface), pro tento případ v Delphi známý
jako TWebBrowser.Document, v podání Microsoftu document DOM objekt. Tento interface pak podporuje spoustu věcí, ale jenom
podle toho jakou verzí Internet Exploreru (resp. Windows) uživatel má.
Každá verze interface pak přináší nějaké rozšíření stávající
funkcionality. Z hlediska samotné implementace se pak jedná stále o jednu a tutéž činnost (protože MSHTML interfacy vycházejí ze
stále stejného základního IDispatch a dědičnost jako taková mezi nimi neexistuje). Tou činností je dotazování, zda daná reference
podporuje požadovaný interface (v tomto případě zda TWebBrowser.Document podporuje např. IHTMLDocument3 interface).
Na tohle dotazování existuje více způsobů (více než uvedu):
1) "as" casting
Jeden z nejčastěji používaných způsobů jak se dostat k požadovanému interface. Jde zkrátka o to, že řekneme kompilátoru: "Hele
kompilátore, poskládej moji aplikaci tak, že když se dostanu za běhu na řádek s "as" castem, zkus referenci interface co dostaneš
přetypovat na interface který chci". Chtít je pěkná vlastnost, ale ne vždy daná reference podporuje požadovaný interface. Takovýto
nezdar je pak korunovaný exception Interface not supported.
Dva příklady použití "as" castingu interface:
var
HTMLDocument: IHTMLDocument2;
begin
HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
ShowMessage(HTMLDocument.url);
end;
var
S: WideString;
begin
S := (WebBrowser1.Document as IHTMLDocument2).url;
ShowMessage(S);
end;
2) dotaz pomocí funkce Supports
Využití funkce Supports bych odhadoval na druhý nejčastější způsob dotazování interface, který je v Delphi k vidění. Jedná se o
bezpečný způsob bez paniky v podobě vyjímky v případě, že reference interface nepodporuje daný interface. Použití na následujícím
příkladu snad není třeba dále rozepisovat (více viz. Delphi help):
var
HTMLDocument: IHTMLDocument2;
begin
if Supports(WebBrowser1.Document, IHTMLDocument2, HTMLDocument) then
ShowMessage(HTMLDocument.url);
end;
3) dotaz pomocí metody QueryInterface
Jde o metodu, kterou má každý IUnknown interface a pomocí které se dá zjistit, zda jeho reference podporuje dotazovaný interface.
Použití je podobné jako u Supports (uvnitř Supports je zabalená stejná podmínka jako v následujícím příkladu, jen se u Supports navíc
testuje vstupní reference na nil, čímž je Supports o něco bezpečnější):
var
HTMLDocument: IHTMLDocument2;
begin
if WebBrowser1.Document.QueryInterface(IHTMLDocument2, HTMLDocument) = S_OK then
ShowMessage(HTMLDocument.url);
end;
Doufám, že jsem ti tím vším nezamotal hlavu a ve zkratce to všechno shrnu. MSHTML nemá děděné interfacy, takže když chceš pracovat
s danou funkcionalitou, dotaž se na podporu daného interface např. jedním z výše uvedených způsobů.
Ne, všechny interfacy MSHTML jsou přímým potomkem IDispatch takže ty si ten IHTMLDocument3 můžeš přecastovat na IHTMLDocument2 když budeš potřebovat. Tzn. že můžeš použít třeba tohle:
var
S: WideString;
HTMLDocument: IHTMLDocument3;
HTMLElementCollection: IHTMLElementCollection;
begin
HTMLDocument := WebBrowser1.Document as IHTMLDocument3;
HTMLElementCollection := HTMLDocument.getElementsByTagName('SPAN');
S := (HTMLDocument as IHTMLDocument2).url;
end;
nebo s použitím TWebBrowser.Document tohle:
var
S: WideString;
HTMLDocument: IHTMLDocument3;
HTMLElementCollection: IHTMLElementCollection;
begin
HTMLDocument := WebBrowser1.Document as IHTMLDocument3;
HTMLElementCollection := HTMLDocument.getElementsByTagName('SPAN');
S := (WebBrowser1.Document as IHTMLDocument2).url;
end