Dan Morris

Is there a recommended way of (a) enumerating open tabs in an existing IE7 window, (b) figuring out which tab is active, and/or (c) setting a specific tab to be active I am working with a .NET forms applications, not an IE7 extension.

The only way I've found to enumerate tabs is to step through the HWND hierarchy and look for windows of class TabWindowClass, but this seems awkward and doesn't let me do (b) or (c). If this is the best way to interact with tabs, does someone have a nice clean example of how to do this in a reasonably robust way, how to get IWebBrowser2 interfaces to individual tabs, activate tabs, etc.

Thanks for any tips you have!

-Dan

http://research.microsoft.com/~dan

(Interestingly, MSDN forums _insists_ that my URL is ~dmorris, which you will no doubt see below this message. It's not. My profile doesn't contain ~dmorris, my Passport information doesn't contain ~dmorris. It's a fascinating MSDN forums bug).



Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Tony Schreiner - MSFT

No, unfortunately IE does not yet expose a tabbed browsing API set. Enumerating windows is also unsupported.

The closest thing we have to (b) is DWebBrowserEvents2::OnWindowStateChanged (http://msdn.microsoft.com/library/default.asp url=/workshop/browser/webbrowser/reference/ifaces/dwebbrowserevents2/windowstatechanged.asp) which enables extensions and IE automation clients to track the visibility state of a given browser window within a tab.

- Tony Schreiner





Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Dan Morris

Sure, but it seems like lots of folks are asking about tabs, so maybe someone has a "nice" wrapper around the not-super-nice process of using COM casts, Window classes, and EnumWindowsProc's that one seems to be able to use to enumerate tabs, close tabs, activate tabs, and find the active tab - all of which are things that various places on the web indicate can be done in a reasonably robust way (generally without much detail).

Thanks!

-Dan


http://research.microsoft.com/~dan




Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Dan Morris

FYI, if anyone is interested, I ended up using the following approach to solving my problem. As a reminder, my problem was basically to 每 from my C# Forms application 每 open url*s in the current tab of an existing IE7 window (launching a url with process.start creates a new tab), and also enumerate all the open URL*s to avoid opening things that were already open. More generally I wanted to do useful stuff with IE from an external application.

1) This is especially difficult in C#, so I created a managed C++ DLL to do the actual work and I talk to it from C#.

2) I use EnumWindows to find all windows of the class IEFrame. Those are just HWND*s and cannot be cast to IWebBrowser objects; you*ll see the point of getting HWND*s at all in a bit.

3) I use the IShellWindows interface 每 obtained using CoCreateInstance(CLSID_ShellWindows) 每 to enumerate all shell windows on the system. I then cast each one to an IWebBrowser2. This actually works for both IE windows and explorer windows, so I need to get rid of the explorer windows. So I call IWebBrowser2->get_hwnd() on each window. For IE tabs, this doesn*t give you the HWND for the tab, it gives you the HWND for the top-level IE window. So I check the get_hwnd() value against my IEFrame HWND list from step (1), and anything that doesn*t match isn*t an IE tab.

4) Now I have IWebBrowser2 objects for each tab, and if I care, I know which IE windows they belong to. If I want to enumerate open URL*s, this is enough; I can call get_LocationURL() to get the URL from each tab.

5) If I want to open a link in the active tab, I can*t just call IWebBrowser2->navigate() or IWebBrowser2->navigate2(), because this opens a new tab. And in fact I can*t even ask which tab is active through this interface. So I cast each one to an IServiceProvider, then to an IOleWindow, on which I call GetWindow, which gives me the HWND for each tab. Then I can call ::IsWindowEnabled(hwnd); the active tab is always enabled and the background tabs are not. Now I know which of my IWebBrowser2*s is the active tab.

6) I get an IHTMLDocument2 from that IWebBrowser2 (via get_document()) and call set_url() on the document, which opens a specified document in that tab (note that using IWebBrowser2->navigate() still opens a new tab, so I use the IHTMLDocument2 approach instead...)

This was something of a mess, but it seems to be reliable and was a good tour through the external interfaces to IE.

-Dan

------------------------------------------
Dan Morris
http://research.microsoft.com/~dan
------------------------------------------





Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Qawi

Hi Dan Morris!

I hope that you can help me out! I have basicly the same issue:(

But I actually just want to get a hold of the last IE window (and the tab inside of this) url.

or even better the html content of it.

It seems like your skills a greater then mine since you fixed it using C++ dll.

but maby you have some code that can do what I asked

I really hope so.. there is nothing on this when searching google:(






Re: Internet Explorer Extension Development Interacting w/tabs in IE7

RyomaEchizen

The last tab/"site" opened is the one that calls IObjectWithSite::SetSite last.




Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Qawi

I really don't understand much of this..

What really sucks is that in Computer Science in my country we don't learn stuff like these..

Do you have an example






Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Qawi

sure that it doesn't just give you the last opened tab not the last tab you where active in (or is active in)

http://msdn.microsoft.com/library/default.asp url=/workshop/components/com/reference/ifaces/iobjectwithsite/setsite.asp






Re: Internet Explorer Extension Development Interacting w/tabs in IE7

rob74

Dan Morris wrote:
FYI, if anyone is interested, I ended up using the following approach to solving my problem. As a reminder, my problem was basically to 每 from my C# Forms application 每 open url*s in the current tab of an existing IE7 window (launching a url with process.start creates a new tab), and also enumerate all the open URL*s to avoid opening things that were already open. More generally I wanted to do useful stuff with IE from an external application.

[...]

3) I use the IShellWindows interface 每 obtained using CoCreateInstance(CLSID_ShellWindows) 每 to enumerate all shell windows on the system. I then cast each one to an IWebBrowser2. This actually works for both IE windows and explorer windows, so I need to get rid of the explorer windows. So I call IWebBrowser2->get_hwnd() on each window. For IE tabs, this doesn*t give you the HWND for the tab, it gives you the HWND for the top-level IE window. So I check the get_hwnd() value against my IEFrame HWND list from step (1), and anything that doesn*t match isn*t an IE tab.

[...]



Hi Dan,

I used a similar approach in a program of mine. Unfortunately, this doesn't seem to work under Windows Vista anymore... When using IShellWindows to enumerate the open shell windows, only the real shell windows are returned, the Internet Explorer windows are ignored. It works with IE7 under XP, but under Vista it doesn't. This is probably some kind of a new security feature... Does anybody here know of a way to make this work again

There is also another observation I made that may be connected to this: If you enter a URL in the address field of a shell window in Vista, the shell window doesn't turn into an IE window as it did before; instead, the URL is opened in a new Internet Explorer window (or a new tab if IE is already open).

Thanks in advance,
Robert




Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Birdman2

Robert,
I'm having the same problem, did you find a solution to this
-Aaron





Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Omrit

Hi,

I am facing a somewhat different problem. I have a web application that goes to the server every 10 seconds to refresh some data.

I'd like to able to know when my application is not the current browser in order to stop the calls to the server to reduce load

can you assist

Thanks!!

Omri





Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Dan Morris

Can you just call ::GetForegroundWindow and see if it matches your WebBrower's HWND That seems to work for me. Other than being the foreground window, there's no real notion of "current browser" that I know of. You could also enumerate all browsers, get their HWND's, and sort by z-order to find the foremost window; this would help in the case where the user is looking at content in your browser but is focused in another application.

-Dan




Re: Internet Explorer Extension Development Interacting w/tabs in IE7

Wolf Logan

Robert:

Sorry to be so late with this, but I think you'll find that these behaviours are caused by IE7's "protected mode" when running under Vista.






Re: Internet Explorer Extension Development Interacting w/tabs in IE7

T E Dixon

This is a bit messy, but it's only proof of concept. This is what I use in C# for finding the active tab.

IEnumerator windows = new SHDocVw.ShellWindowsClass().GetEnumerator();
while (windows.MoveNext())
{
if ((windows.Current is SHDocVw.IWebBrowser2) && ((windows.Current as SHDocVw.IWebBrowser2).HWND == Explorer.HWND))
{
IntPtr hwnd; ((windows.Current as SHDocVw.IWebBrowser2).Document as IOleWindow).GetWindow(out hwnd);

if (IsWindowVisible(hwnd))
{
MessageBox.Show(((windows.Current as SHDocVw.IWebBrowser2).Document as mshtml.IHTMLDocument2).title);
break;
}
}
}

So far now I've been able do the following things with IE7 via various tricks: open a tab, close a tab, scrape data from a page, change the tab label, enumerate open tabs, navigate a particular tab to a new page and handle events like NavigateComplete2 with respect to certain tabs.
The only thing I haven't been able to do is activate a tab; that is, bring it to the front as if the user had selected it. For that, I have found the HWnd using a variation on the code above, and tried the following API calls: SetFocus, SetForegroundWindow, ShowWindow, SwitchToThisWindow, BringWindowToTop, SetActiveWindow and EnableWindow. I noticed that GetParent(GetParent(GetParent(HWnd))) returns the same HWnd as the main IE7 window, so I tried all these functions on HWnd's parent and HWnd's parent's parent as well.
Since the code above is different to what you described Dan, I've been wondering if I've done something wrong in finding the HWnd of the active tab. However, simply casting the IWebBrowser2 object to an IServiceProvider and then/or an IOleWindow returns null. Hoping you or someone else has had some success with this.