Click here to Skip to main content
15,867,835 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 311.1K   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

 
Questionvb.NET Translation Pin
Member 102852932-Aug-18 22:49
professionalMember 102852932-Aug-18 22:49 
BugFlash videos doesn't get played. Pin
Member 1300495619-Sep-17 2:50
Member 1300495619-Sep-17 2:50 
BugGUI freezing on navigating Pin
Emiliarge23-Aug-14 23:01
professionalEmiliarge23-Aug-14 23:01 
QuestionDocument.All.Item and InvokeMember help Pin
zouhair samir13-Sep-13 15:57
zouhair samir13-Sep-13 15:57 
GeneralMy vote of 5 Pin
LVMONTIEL5-May-11 1:05
LVMONTIEL5-May-11 1:05 
GeneralDrag Out tabs Pin
Fullmetal9901224-Apr-11 3:54
Fullmetal9901224-Apr-11 3:54 
QuestionGreat Job, Help Please Pin
young10120-Nov-09 19:59
young10120-Nov-09 19:59 
GeneralHelp with tabs!!! Pin
ALEX CHIHAI7-Oct-09 2:33
ALEX CHIHAI7-Oct-09 2:33 
GeneralYou Rock! Pin
Shannon McCoy19-Aug-09 3:04
Shannon McCoy19-Aug-09 3:04 
GeneralVB.Net implementation Pin
Jeroen De Dauw23-Feb-09 9:12
Jeroen De Dauw23-Feb-09 9:12 
GeneralHere is your 5! Pin
Aamer Alduais30-Nov-08 0:16
Aamer Alduais30-Nov-08 0:16 
QuestionHide the Find Dialog when swichting to differnet tab? Pin
TexG29-Feb-08 3:57
TexG29-Feb-08 3:57 
QuestionI cannot call javascript with this browser. Could you give me a sample solution? Pin
Woo Hyuck Choi29-Dec-07 2:47
Woo Hyuck Choi29-Dec-07 2:47 
QuestionCan we use web browser from stream? Pin
Ariston Darmayuda19-Jul-07 6:27
Ariston Darmayuda19-Jul-07 6:27 
GeneralChanging printer at run time Pin
temp->next20-Jun-07 1:25
temp->next20-Jun-07 1:25 
Hello,
I have a windows application in which user can select a particular HTML file and sent it to the selected printer.
For this i am using AXshdocvw.AXwebbrowser activex in which first I load the html. Then based on selected printer, I sent the request.

The problem is even if I change the default printer at the run time, the print request goes to the printer which was selected for the first time.


Below is the code snippet:
l_WshNetwork = new WshNetwork();
l_WshNetwork.SetDefaultPrinter("Printer Selected by user");
axW_PrintBrowser.Navigate(null, ref empty, ref empty, ref empty, ref empty); axW_PrintBrowser.Navigate("Print file location", ref empty, ref empty, ref empty, ref empty);
// Load the print job in the browser
for (; axW_PrintBrowser.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE; )
{
System.Windows.Forms.Application.DoEvents();
}
// By this method, the printing occurs.
axW_PrintBrowser.ExecWB(SHDocVw.OLECMDID.OLECMDID_PRINT, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref empty, ref empty);


Any help will be of great use.

Regards,
Akshay
GeneralVery good Pin
Curious Programmer26-Mar-07 6:40
Curious Programmer26-Mar-07 6:40 
QuestionPage not loaded if switched to another tab Pin
BalaVikram6-Feb-07 1:24
BalaVikram6-Feb-07 1:24 
GeneralWindow-name resolution with WebBrowser 2.0 Pin
BrightSoul22-Jun-06 0:13
BrightSoul22-Jun-06 0:13 
AnswerRe: Window-name resolution with WebBrowser 2.0 Pin
The Cake of Deceit8-Sep-08 11:40
The Cake of Deceit8-Sep-08 11:40 
GeneralGreat work...one question Pin
Ross1000030-Mar-06 18:15
Ross1000030-Mar-06 18:15 
GeneralProxy problems Pin
cdemez6-Mar-06 7:29
cdemez6-Mar-06 7:29 
QuestionHow can I close the tab inside page? Pin
Lisana30-Jan-06 11:12
Lisana30-Jan-06 11:12 
AnswerRe: How can I close the tab inside page? Pin
ohmzz10-May-10 6:01
ohmzz10-May-10 6:01 
Questionhow 2 work with combo box using axWebBrowser1 ? Pin
vedmack9-Jan-06 9:51
vedmack9-Jan-06 9:51 
GeneralGreat work, just one question Pin
Drewes5-Jan-06 2:32
Drewes5-Jan-06 2:32 

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.