Retrieving the "highest level frame" from SHDocVw WebBrowser control

1.1k views Asked by At

The documentation for the DocumentComplete event mentions near the end:

In the loading process, the highest level frame, which is not necessarily the top-level frame, fires the final DWebBrowserEvents2::DocumentComplete event. At this time, the pDisp parameter is the same as the IDispatch interface pointer of the highest level frame.

What is the difference between the highest level frame and the top-level frame, and how do I get a reference to the highest level frame?

2

There are 2 answers

1
Sheng Jiang 蒋晟 On BEST ANSWER

Assume you have a web site that has a top-level frame set that contains a banner frame on top, a menu frame on the left, and a content frame on the right. Each anchor element in the menu frame has a target attribute set to the content frame. There are some iframes on each content page that would be target pages of menu items.

Now you click a menu link on the left. The frame set itself does not change, nor does the menu frame. The only frame that is navigating is the content frame, the highest level frame in the navigation.

You can get the reference of the highest level navigating frame from the parameter of the first NavigateComplete2 event. IE then parse the frames on the content page to see if there are additional frames to load. Additional NavigateComplete2 and DocumentComplete2 events were raised when the rest of the iframes on the content page are loaded, and finally the DocumentComplete2 event is raised for the content frame.

0
Erx_VB.NExT.Coder On

if you are doing this to test to see if document has truely loaded, there is a better way to test for this particular event (ie: pDisp objects). Look at some of my webbrowser-control related answers.

so here, you want to run a difference counter between NavComplete and DocComplete, however, if you do it normally, it won't work, as NavComplete gets called more than once on many frames, so you need to check to see if the NavComplete being called is a unique one. In vb its just comparing one object to another using the Is operator, in C# i understand Is isn't available, so you just do a normal object comparison.

So, you keep a list of every pDisp objects that NavComplete has posted, and before adding each one, you check the entire collection to make sure the pDisp being added hasn't been added before (ie: is unique), eg: If pDisp Is pDispCollection(i) Then and "i" being your increment counter in your for each loop.

Now, the pDisp's that DocComplete posts are ALWAYS unique (so you dont have to worry about it getting called more than once for each new/unique pDisp), so every time a pDisp occurs, you just find which one it is from the collection, and remove it.

Once you are at 0, you know it has truely finished :).

There are other things you need to test for but this is a big/main important one and will increase your accuracy big time (much more than just checking for .busy and .readystate).

Let me know how it goes or if you need more help.