Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C#

Extended .NET 2.0 WebBrowser Control

Rate me:
Please Sign up or sign in to vote.
4.90/5 (118 votes)
29 Mar 20069 min read 1.3M   37.7K   341  
Extending the .NET 2.0 WebBrowser control.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;

namespace ExtendedWebBrowser2
{
  /// <summary>
  /// Manages the tabs, and their contents
  /// </summary>
  class WindowManager
  {
    public WindowManager(TabControl tabControl)
    {
      _tabControl = tabControl;
      _tabControl.SelectedIndexChanged += new EventHandler(tabControl_SelectedIndexChanged);
    }

    private TabControl _tabControl;

    /// <summary>
    /// Closes the active tab
    /// </summary>
    public void Close()
    {
      // Find the active page
      TabPage page = this._tabControl.SelectedTab;
      // Check wheter there is actually a page selected
      if (page != null)
      {
        // Remove the page
        this._tabControl.TabPages.Remove(page);
        // Dispose the page (controls on the page are also disposed this way)
        page.Dispose();
      }
      if (_tabControl.TabPages.Count == 0)
        _tabControl.Visible = false;
    }

    /// <summary>
    /// Opens a new browser tab, and navigates to the home page
    /// </summary>
    /// <returns>The instance of the browser created</returns>
    public ExtendedWebBrowser New()
    {
      return New(true);
    }

    /// <summary>
    /// Opens a new browser tab
    /// </summary>
    /// <param name="navigateHome">true to immediately navigate to the homepage, otherwise false</param>
    /// <returns>The instance of the browser created</returns>
    // We cannot dispose the browsercontrol here
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
    public ExtendedWebBrowser New(bool navigateHome)
    {
      // Create a new tab page
      TabPage page = new TabPage();
      // Create a new browser control
      BrowserControl browserControl = new BrowserControl();
      // Set the page as the Tag of the browser control, and vice-versa, this will come in handy later
      browserControl.Tag = page;
      page.Tag = browserControl;
      page.Text = Properties.Resources.DefaultBrowserTitle;
      // Dock the browser control
      browserControl.Dock = DockStyle.Fill;
      // Add the browser control to the tab page
      page.Controls.Add(browserControl);
      if (navigateHome)
      {
        // Navigate to the home page
        browserControl.WebBrowser.GoHome();
      }
      // Wire some events
      browserControl.WebBrowser.StatusTextChanged += new EventHandler(WebBrowser_StatusTextChanged);
      browserControl.WebBrowser.DocumentTitleChanged += new EventHandler(WebBrowser_DocumentTitleChanged);
      browserControl.WebBrowser.CanGoBackChanged += new EventHandler(WebBrowser_CanGoBackChanged);
      browserControl.WebBrowser.CanGoForwardChanged += new EventHandler(WebBrowser_CanGoForwardChanged);
      browserControl.WebBrowser.Navigated += new WebBrowserNavigatedEventHandler(WebBrowser_Navigated);
      browserControl.WebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
      browserControl.WebBrowser.Quit += new EventHandler(WebBrowser_Quit);
      // Add the new page to the tab control
      _tabControl.TabPages.Add(page);
      _tabControl.SelectedTab = page;
      _tabControl.Visible = true;
      return browserControl.WebBrowser;
    }


    void WebBrowser_Quit(object sender, EventArgs e)
    {
      // This event is launched when window.close() is called from script
      ExtendedWebBrowser brw = sender as ExtendedWebBrowser;
      if (brw == null)
        return;
      // See which page it was on...
      BrowserControl bc = BrowserControlFromBrowser(brw);
      if (bc == null)
        return;

      TabPage page = bc.Tag as TabPage;
      if (page == null)
        return;

      // We got a page, remove & dispose it.
      _tabControl.TabPages.Remove(page);
      page.Dispose();

      if (_tabControl.TabPages.Count == 0)
        _tabControl.Visible = false;
    }

    public void Open(Uri url)
    {
      ExtendedWebBrowser browser = this.New(false);
      browser.Navigate(url);
    }

    #region Events that cause the status of toolbar buttons or menu items to change
    void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
      CheckCommandState();
    }

    void WebBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
      CheckCommandState();
    }

    void WebBrowser_CanGoForwardChanged(object sender, EventArgs e)
    {
      CheckCommandState();
    }

    void WebBrowser_CanGoBackChanged(object sender, EventArgs e)
    {
      CheckCommandState();
    }

    void tabControl_SelectedIndexChanged(object sender, EventArgs e)
    {
      CheckCommandState();
    }

    #endregion


    private void CheckCommandState()
    {
      BrowserCommands commands = BrowserCommands.None;
      if (ActiveBrowser != null)
      {
        if (ActiveBrowser.CanGoBack)
          commands |= BrowserCommands.Back;
        if (ActiveBrowser.CanGoForward)
          commands |= BrowserCommands.Forward;
        if (ActiveBrowser.IsBusy)
          commands |= BrowserCommands.Stop;
        // Add the default commands
        // You could do some aditional checking here. 
        // For example, Home could be disabled if the user is allready on the home page
        commands |= BrowserCommands.Home;
        commands |= BrowserCommands.Search;
        commands |= BrowserCommands.Print;
        commands |= BrowserCommands.PrintPreview;
        commands |= BrowserCommands.Reload;
      }

      //// If it's not the active browser, return aswel..
      //if (extendedWebBrowser != ActiveBrowser)
      //  return;

      OnCommandStateChanged(new CommandStateEventArgs(commands));
    }

    void WebBrowser_DocumentTitleChanged(object sender, EventArgs e)
    {
      // Update the title of the tab page of the control.
      ExtendedWebBrowser ewb = sender as ExtendedWebBrowser;
      // Return if we got nothing (shouldn't happen)
      if (ewb == null) return;

      // This is a little nasty. The Extended Web Browser is nested in 
      // a panel, wich is nested in the browser control
      BrowserControl bc = BrowserControlFromBrowser(ewb);
      // If we got null, return
      if (bc == null) return;
      
      // The Tag of the BrowserControl should point to the TabPage
      TabPage page = bc.Tag as TabPage;
      // If not, return
      if (page == null) return;

      // Update the tabPage
      // Keep it user-friendly, don't do those awful long web page titles 
      // in tabs and make sure the title is never empty
      string documentTitle = ewb.DocumentTitle;
      if (string.IsNullOrEmpty(documentTitle))
      {
        documentTitle = Properties.Resources.DefaultBrowserTitle;
      }
      else if (documentTitle.Length > 30)
      {
        documentTitle = documentTitle.Substring(0, 30) + "...";
      }
      page.Text = documentTitle;
      // Set the full title as a tooltip
      page.ToolTipText = ewb.DocumentTitle;

    }

    void WebBrowser_StatusTextChanged(object sender, EventArgs e)
    {
      // First, see if the active page is calling, or another page
      ExtendedWebBrowser ewb = sender as ExtendedWebBrowser;
      // Return if we got nothing (shouldn't happen)
      if (ewb == null) return;

      // This is a little nasty. The Extended Web Browser is nested in 
      // a panel, wich is nested in the browser control
      BrowserControl bc = BrowserControlFromBrowser(ewb);

      // The Tag of the BrowserControl should point to the TabPage
      TabPage page = bc.Tag as TabPage;
      // If not, return
      if (page == null) return;

      // See if 'page' is the active page
      if (this._tabControl.SelectedTab == page)
      {
        // Yep, send the event that updates the status bar text
        OnStatusTextChanged(new TextChangedEventArgs(ewb.StatusText));
      }
    }

    public event EventHandler<TextChangedEventArgs> StatusTextChanged;

    /// <summary>
    /// Raises the StatusTextChanged event
    /// </summary>
    /// <param name="e"></param>
    protected virtual void OnStatusTextChanged(TextChangedEventArgs e)
    {
      if (StatusTextChanged != null)
        StatusTextChanged(this, e);
    }

    private static BrowserControl BrowserControlFromBrowser(ExtendedWebBrowser browser)
    {
      // This is a little nasty. The Extended Web Browser is nested in 
      // a panel, wich is nested in the browser control

      // Since we want to avoid a NullReferenceException, do some checking

      // Check if we got a extended web browser
      if (browser == null)
        return null;

      // Check if it got a parent
      if (browser.Parent == null)
        return null;

      // Return the parent of the parent using a safe cast.
      return browser.Parent.Parent as BrowserControl;
    }

    public ExtendedWebBrowser ActiveBrowser
    {
      get
      {
        TabPage page = _tabControl.SelectedTab;
        if (page != null)
        {
          BrowserControl control = page.Tag as BrowserControl;
          if (control != null)
            return control.WebBrowser;
        }
        return null;
      }
    }

    public event EventHandler<CommandStateEventArgs> CommandStateChanged;
    protected virtual void OnCommandStateChanged(CommandStateEventArgs e)
    {
      if (CommandStateChanged != null)
        CommandStateChanged(this, e);
    }




  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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
Web Developer
Chile Chile
I am
- born in The Netherlands
- living in Chile together with my wife.
- a Microsoft Certified Professional Developer on all 3 areas (Windows, Web and Enterprise)
- an MCITP on Microsoft SQL Server 2005 (Database Administrator)
- an active programmer for about 14 years.
- a business owner, of a Dutch company called "The Wheel Automatisering" (http://www.thewheel.nl)
- a coder in C#, VB.Net and Managed C++.
- someone who likes to share knowledge

For fun I like to go out with my dogs, enjoy the sun or write some articles that I share with the community.

Comments and Discussions