Click here to Skip to main content
15,887,485 members
Articles / Web Development / HTML
Article

Multi Tab WebBrowser

Rate me:
Please Sign up or sign in to vote.
4.82/5 (37 votes)
23 May 20053 min read 312K   8.3K   88   61
A webbrowser example of how to open new web windows in new tabs.

Sample Image - MultiTabWebBrowser.jpg

Introduction

One web browser feature that is growing in popularity is the ability to open different tabs, or sub-pages, within the same browser window. Using tabs to separate multiple pages keeps the desktop tidy, while browsing multiple sites.

The web browser is also efficient for viewing multiple local files as it supports many files formats.

This code shows how to implement this feature, and also implements the following features: Print, Print Preview, Page properties, Options screen, Find Dialog, View page source, and more.

Implementing the Multi Tab Feature

This feature is mainly implemented by the NewWindow2 event.

The NewWindow2 event occurs when a new window is to be created for displaying a resource. This event occurs before a new window is created from the WebBrowser control. For example, this event occurs in response to a navigation that is targeted to a new window or to a scripted window.open method.

To specify that your browser program is to be used when a new window is opened, set the ppDisp parameter equal to the Application object. In this scenario, if a user chooses to open a web page in a new window, the new window in your program is used to display the new web page.

Additionally, set the RegisterAsBrowser property to true. This setting causes the new WebBrowser control to participate in window-name resolution. For example, if the window name is used elsewhere in the script, this control is used instead of a newly created one because the control examines all the existing window names before opening a new window.

On this event, we dynamically create a new instance of a tab page and a web browser as child by calling the CreateNewWebBrowser() method, where each web browser object has a tag object containing additional data on the corresponding web browser:

C#
private void axWebBrowser1_NewWindow2(object sender, 
                AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
  AxSHDocVw.AxWebBrowser _axWebBrowser = CreateNewWebBrowser();
  e.ppDisp = _axWebBrowser.Application;
  _axWebBrowser.RegisterAsBrowser = true;
}

private AxSHDocVw.AxWebBrowser CreateNewWebBrowser()
{
  AxSHDocVw.AxWebBrowser _axWebBrowser = new AxSHDocVw.AxWebBrowser();
  _axWebBrowser.Tag = new HE_WebBrowserTag();
  TabPage _TabPage = new TabPage();
  _TabPage.Controls.Add(_axWebBrowser);
  _axWebBrowser.Dock = DockStyle.Fill;
  _axWebBrowser.BeforeNavigate2 += new 
           AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(
           this.axWebBrowser1_BeforeNavigate2);
  _axWebBrowser.DocumentComplete += new 
           AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(
           this.axWebBrowser1_DocumentComplete);
  _axWebBrowser.NavigateComplete2 += new 
           AxSHDocVw.DWebBrowserEvents2_NavigateComplete2EventHandler(
           this.axWebBrowser1_NavigateComplete2);
  _axWebBrowser.NavigateError += new 
           AxSHDocVw.DWebBrowserEvents2_NavigateErrorEventHandler(
           this.axWebBrowser1_NavigateError);
  _axWebBrowser.NewWindow2 += new 
           AxSHDocVw.DWebBrowserEvents2_NewWindow2EventHandler(
           this.axWebBrowser1_NewWindow2);
  _axWebBrowser.ProgressChange += new 
           AxSHDocVw.DWebBrowserEvents2_ProgressChangeEventHandler(
           this.axWebBrowser1_ProgressChange);
  _axWebBrowser.StatusTextChange += new 
           AxSHDocVw.DWebBrowserEvents2_StatusTextChangeEventHandler(
           this.axWebBrowser1_StatusTextChange);
  _axWebBrowser.TitleChange += new 
           AxSHDocVw.DWebBrowserEvents2_TitleChangeEventHandler(
           this.axWebBrowser1_TitleChange);
  _axWebBrowser.CommandStateChange += new 
           AxSHDocVw.DWebBrowserEvents2_CommandStateChangeEventHandler(
           this.axWebBrowser1_CommandStateChange);

  tabControl1.TabPages.Add(_TabPage);
  tabControl1.SelectedTab = _TabPage;
  return _axWebBrowser;
}

Each instance of a web browser will have in its tag an HE_WebBrowserTag object that holds some details on that web browser object:

C#
public class HE_WebBrowserTag
{
  public int _TabIndex = 0;
  public bool _CanBack = false;
  public bool _CanForward = false;
}

Invoke the Find, View Source, and Options Dialog Boxes

Warning: this sample uses an undocumented command-group GUID that is subject to change in the future. Although this sample was tested to work correctly with Internet Explorer 6 and earlier, there is no guarantee that these techniques will continue to work successfully in future versions.

Define IOleCommandTarget in Visual C# .NET

To define a .NET interface to obtain a reference to a Component Object Model (COM) interface, follow these steps:

  1. Assign the interface the GUID of the appropriate COM interface.
  2. Include type declarations for all the methods of the interface.
  3. Include references to the Mshtml.dll file and the Shdocvw.dll file.

    To do this in your Visual C# .NET project, follow these steps:

    1. Click Add Reference on the Project menu.
    2. Click the COM tab.
    3. Double-click Microsoft HTML Object Library and Microsoft Internet Controls.
  4. Include the following interface declaration just before your application's namespace declaration to add a reference to the Microsoft HTML (MSHTML) IOleCommandTarget interface:
    C#
    using System;
    using System.Runtime.InteropServices;
    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
    public struct OLECMDTEXT
    {
        public uint cmdtextf;
        public uint cwActual;
        public uint cwBuf;
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst=100)]public char rgwz;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct OLECMD
    {
        public uint cmdID;
        public uint cmdf;
    }
    
    // Interop definition for IOleCommandTarget.
    [ComImport,
    Guid("b722bccb-4e68-101b-a2bc-00aa00404770"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleCommandTarget
    {
        //IMPORTANT: The order of the methods is critical here. You
        //perform early binding in most cases, so the order of the methods
        //here MUST match the order of their vtable layout (which is determined
        //by their layout in IDL). The interop calls key off the vtable ordering,
        //not the symbolic names. Therefore, if you 
        //switched these method declarations
        //and tried to call the Exec method 
        //on an IOleCommandTarget interface from your
        //application, it would translate 
        //into a call to the QueryStatus method instead.
        void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds,
            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] 
            OLECMD[] prgCmds, ref OLECMDTEXT CmdText);
        void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, 
                  ref object pvaIn, ref object pvaOut);
    }

Define the Command GUID for CGID_IWebBrowser

You must also define the GUID for CGI_IWebBrowser to inform MSHTML how to process your command IDs. Use the Microsoft .NET Framework class GUID to do this:

C#
private Guid cmdGuid = new Guid("ED016940-BD5B-11CF-BA4E-00C04FD70816");

private enum MiscCommandTarget { Find = 1, ViewSource, Options }

Call Exec()

Finally, encapsulate the calls to the Exec method in three separate method calls. Each call assumes the existence of a hosted instance of the WebBrowser control that is named webBrowser:

C#
private mshtml.HTMLDocument GetDocument()
{
    try
    {
        mshtml.HTMLDocument htm = (mshtml.HTMLDocument)axWebBrowser2.Document;
        return htm;
    }
    catch
    {
        throw (new Exception("Cannot retrieve" + 
               " the document from the WebBrowser control"));
    }
}

public void ViewSource()
{
    IOleCommandTarget cmdt;
    Object o = new object();
    try
    {
        cmdt = (IOleCommandTarget)GetDocument();
        cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.ViewSource,
        (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
    }
    catch(Exception e)
    {
        System.Windows.Forms.MessageBox.Show(e.Message);
    }
}

public void Find()
{
    IOleCommandTarget cmdt;
    Object o = new object();
    try
    {
        cmdt = (IOleCommandTarget)GetDocument();
        cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Find,
        (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
    }
    catch(Exception e)
    {
        System.Windows.Forms.MessageBox.Show(e.Message);
    }
}

public void InternetOptions()
{
    IOleCommandTarget cmdt;
    Object o = new object();
    try
    {
        cmdt = (IOleCommandTarget)GetDocument();
        cmdt.Exec(ref cmdGuid, (uint)MiscCommandTarget.Options,
        (uint)SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref o, ref o);
    }
    catch
    {
        // NOTE: Because of the way that this CMDID is handled in Internet Explorer,
        // this catch block will always fire, even though the dialog box
        // and its operations completed successfully. You can suppress this
        // error without causing any damage to your host.
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: cookie ... problems ... Help plz Pin
amb980025-Jul-05 21:31
amb980025-Jul-05 21:31 
GeneralRe: cookie ... problems ... Help plz Pin
enjoycrack25-Jul-05 22:19
enjoycrack25-Jul-05 22:19 
GeneralRe: cookie ... problems ... Help plz Pin
amb980026-Jul-05 7:43
amb980026-Jul-05 7:43 
GeneralRe: cookie ... problems ... Help plz Pin
enjoycrack26-Jul-05 17:42
enjoycrack26-Jul-05 17:42 
Generaledit and copy are not working for me Pin
Anonymous21-Jun-05 11:33
Anonymous21-Jun-05 11:33 
GeneralRemoving TabPages dynamically Pin
Member 10884147-Jun-05 2:30
Member 10884147-Jun-05 2:30 
GeneralTechConnect - Tabbed, IE + Gecko, Favorites, Media Player, RSS, more... Pin
amb980023-May-05 9:10
amb980023-May-05 9:10 
GeneralNetron's version: docking and favorites. Pin
[Gone]23-May-05 5:04
[Gone]23-May-05 5:04 
Nice article Roll eyes | :rolleyes: . It's not easy to write about and code on top of IE's horrible inner-mechanism. If you have time, take a look a the multi-tabbed browser I made[^] some time ago (for fun). It has dockable windows and favorites as well, used to demonstrate some of Neon's features. Took me a few thousand lines to get it working.

It's all open source as well, of course.


Keep shining!





I thought about it,
I stood up
and I did it.
The Netron Project


GeneralProgress Bar revised to work Pin
badass19-May-05 18:34
badass19-May-05 18:34 
GeneralRe: Progress Bar revised to work Pin
Ronit H23-May-05 10:19
Ronit H23-May-05 10:19 
GeneralRe: Progress Bar revised to work Pin
badass23-May-05 10:26
badass23-May-05 10:26 
GeneralPopup in new browser window Pin
Member 54277810-May-05 10:37
Member 54277810-May-05 10:37 
Generalprint landspace Pin
kateerre21-Mar-05 23:51
kateerre21-Mar-05 23:51 
GeneralRe: print landspace Pin
Ronit H22-Mar-05 2:06
Ronit H22-Mar-05 2:06 
GeneralRe: print landspace Pin
kateerre22-Mar-05 4:14
kateerre22-Mar-05 4:14 
GeneralRe: print landspace Pin
Ronit H23-Mar-05 8:04
Ronit H23-Mar-05 8:04 
GeneralWow Great work Pin
sanjit_rath20-Mar-05 8:16
sanjit_rath20-Mar-05 8:16 
GeneralRe: Wow Great work Pin
sanjit_rath20-Mar-05 8:32
sanjit_rath20-Mar-05 8:32 
QuestionHave you seen Avant Browser? Pin
Peter Tewkesbury17-Mar-05 4:21
professionalPeter Tewkesbury17-Mar-05 4:21 
AnswerRe: Have you seen Avant Browser? Pin
Harm Salomons25-May-05 2:41
Harm Salomons25-May-05 2:41 
GeneralRe: Have you seen Avant Browser? Pin
JRBlack1022-Jun-05 7:46
JRBlack1022-Jun-05 7:46 
AnswerRe: Have you seen Avant Browser? Pin
JRBlack1022-Jun-05 7:47
JRBlack1022-Jun-05 7:47 
GeneralGreat ! Pin
Le_MuLoT17-Mar-05 3:20
Le_MuLoT17-Mar-05 3:20 
GeneralCannot trap "Internet Explorer Script Error" despite advanced IE settings Pin
stewartwood28-Feb-05 3:14
stewartwood28-Feb-05 3:14 
GeneralRe: Cannot trap "Internet Explorer Script Error" despite advanced IE settings Pin
stewartwood1-Mar-05 2:48
stewartwood1-Mar-05 2:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.