Mega Code Archive

 
Categories / Delphi / LAN Web TCP
 

How to get all documents for all frames from a TWebbrowser

Title: How to get all documents for all frames from a TWebbrowser Question: If youre stuck when it comes to frames in a TWebBrowser and dont know how to get a grip to the documents inside the frames, this article is for you. Answer: !! UPDATED ON 24.12.2007------ (Added IHTMLFrameBase for questioning the framename and changed logic because of wrong exit of procedures.) THIS IS THE NEW ARTICLE. OLD ONE (ArtID:1989 "Loop through frames of a TWebBrowser".) IS VOID NOW :-) This is my second article on the subject. As i wrote the first one, in early 2001, i was satisfied with what i achieved, as it was sufficient for the task at hand. This year i had another project to do that handled with the same subject: Automatically filling forms with the help of a webbrowser-component. But as the project growd i had to face the fact that some websites denied access to certain frames, or at least it seemed so. As i studied the html-code for the websites that did not work i realised that their code was build on javascript. In fact, all the FRAMESET and FRAME code was depending on javascript-functions like in this example: document.write(""); document.write(""); If you try to get the documents behind the frames with your normal Webbrowser.frames[0] functions youre lost....well at first. I discovered a function which will do the hard work for you and get any desired frame-document you like of the entire collection. For the function to work you need at least these units: uses Sysutils, MSHTML, ActiveX, SHDocVw; I used the EmbeddedWB component with updated MSHTML and ShDocVw_EWB to accomplish the task. So if something does not work for you consider upgrading or installing the EmbeddedWB component from this link: http://www.bsalsa.com To use this function just Navigate to an URL with frames and pass your webbrowser-component and a frame-name to search for. And now comes the function --------------------------------------------------------------------- function GetFrameByName(ABrowser:TWebBrowser;aFrameName: string): IHTMLDocument2; var searchdoc : IHTMLDocument2; // temporarily holds the resulting page FoundIt : boolean // Flag if we found the right Frame // This is the inner recursive portion of the function function Enum(AHTMLDocument:IHTMLDocument2;aFrameName:string):boolean; var OleContainer: IOleContainer; EnumUnknown: IEnumUnknown; Unknown: IUnknown; Fetched: LongInt; WebBrowser: IWebBrowser; FBase : IHTMLFrameBase; begin Result:=True; if not Assigned(AHtmlDocument) then Exit; if not Supports(AHtmlDocument, IOleContainer, OleContainer) then Exit; if Failed(OleContainer.EnumObjects(OLECONTF_EMBEDDINGS, EnumUnknown)) then Exit; while (EnumUnknown.Next(1, Unknown, @Fetched)=S_OK) do begin if Supports(Unknown, IHTMLFrameBase,FBase) then begin // Here we ask if we have the right Frame if LowerCase(FBase.name) = LowerCase(aFrameName) then begin if Supports(Unknown, IWebBrowser, WebBrowser) then begin searchdoc := (WebBrowser.Document as IHTMLDocument2); FoundIt:=true; exit; end; end; end; if NOT (FoundIt) then begin if Supports(Unknown, IWebBrowser, WebBrowser) then begin Result:=Enum((WebBrowser.Document as IHtmlDocument2),aFrameName); if not Result then Exit; end; end else exit; end; end; begin FoundIt := false; result := nil; // just in case Enum((ABrowser.Document as IHTMLDocument2),aFrameName); if FoundIt then result := searchdoc else result := nil; end; --------------------------------------------------------------------- If you need to get a frame-document by id (integer) you could use the function like this: --------------------------------------------------------------------- function GetFrameByID(ABrowser:TWebBrowser;aFrameID: integer): IHTMLDocument2; var searchdoc : IHTMLDocument2; // temporarily holds the resulting page i : integer; // IDcount // This is the inner recursive portion of the function function Enum(AHTMLDocument:IHTMLDocument2;aFrameID:integer):boolean; var OleContainer: IOleContainer; EnumUnknown: IEnumUnknown; Unknown: IUnknown; Fetched: LongInt; WebBrowser: IWebBrowser; i : integer; begin inc(i); Result:=True; if not Assigned(AHtmlDocument) then Exit; if not Supports(AHtmlDocument, IOleContainer, OleContainer) then Exit; if Failed(OleContainer.EnumObjects(OLECONTF_EMBEDDINGS, EnumUnknown)) then Exit; while (EnumUnknown.Next(1, Unknown, @Fetched)=S_OK) do begin if Supports(Unknown, IHMTLFrameBase, FBase) then begin // Here we ask if we have the right Frame if i = aFrameID then begin if Supports(Unknown, IWebBrowser, WebBrowser) then begin searchdoc := (WebBrowser.Document as IHTMLDocument2); FoundIt := true; exit; end; end; end; if NOT (FoundIt) then begin if Supports(Unknown, IWebBrowser, WebBrowser) then begin Result:=Enum((WebBrowser.Document as IHtmlDocument2),aFrameName); if not Result then Exit; end; end else exit; end; end; begin i := -1; result := nil; // just in case Enum((ABrowser.Document as IHTMLDocument2),aFrameID); if FoundIt then result := searchdoc else result := nil; end; --------------------------------------------------------------------- This is the result of another 3 days of my live spend coding. I hope you can use this for your purposes. Happy coding.