Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version
Go to top

Extended .NET 2.0 WebBrowser Control

, 29 Mar 2006
Extending the .NET 2.0 WebBrowser control.
using System;
using System.Security;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using System.Security.Permissions;

namespace ExtendedWebBrowser2
{
  /// <summary>
  /// An extended version of the <see cref="WebBrowser"/> control.
  /// </summary>
  class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
  {

    private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2;

    /// <summary>
    /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. 
    /// Called by the control when the underlying ActiveX control is created. 
    /// </summary>
    /// <param name="nativeActiveXObject"></param>
    [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void AttachInterfaces(object nativeActiveXObject)
    {
      this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
      base.AttachInterfaces(nativeActiveXObject);
    }

    /// <summary>
    /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. 
    /// Called by the control when the underlying ActiveX control is discarded. 
    /// </summary>
    [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void DetachInterfaces()
    {
      this.axIWebBrowser2 = null;
      base.DetachInterfaces();
    }

    /// <summary>
    /// Returns the automation object for the web browser
    /// </summary>
    public object Application
    {
      get { return axIWebBrowser2.Application; }
    }


    System.Windows.Forms.AxHost.ConnectionPointCookie cookie;
    WebBrowserExtendedEvents events;

    /// <summary>
    /// This method will be called to give you a chance to create your own event sink
    /// </summary>
    [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void CreateSink()
    {
      // Make sure to call the base class or the normal events won't fire
      base.CreateSink();
      events = new WebBrowserExtendedEvents(this);
      cookie = new AxHost.ConnectionPointCookie(this.ActiveXInstance, events, typeof(UnsafeNativeMethods.DWebBrowserEvents2));
    }

    /// <summary>
    /// Detaches the event sink
    /// </summary>
    [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void DetachSink()
    {
      if (null != cookie)
      {
        cookie.Disconnect();
        cookie = null;
      }
    }

    /// <summary>
    /// Fires when downloading of a document begins
    /// </summary>
    public event EventHandler Downloading;
    
    /// <summary>
    /// Raises the <see cref="Downloading"/> event
    /// </summary>
    /// <param name="e">Empty <see cref="EventArgs"/></param>
    /// <remarks>
    /// You could start an animation or a notification that downloading is starting
    /// </remarks>
    protected void OnDownloading(EventArgs e)
    {
      if (Downloading != null)
        Downloading(this, e);
    }

    /// <summary>
    /// Fires when downloading is completed
    /// </summary>
    /// <remarks>
    /// Here you could start monitoring for script errors. 
    /// </remarks>
    public event EventHandler DownloadComplete;
    /// <summary>
    /// Raises the <see cref="DownloadComplete"/> event
    /// </summary>
    /// <param name="e">Empty <see cref="EventArgs"/></param>
    protected virtual void OnDownloadComplete(EventArgs e)
    {
      if (DownloadComplete != null)
        DownloadComplete(this, e);
    }


    /// <summary>
    /// Fires before navigation occurs in the given object (on either a window or frameset element).
    /// </summary>
    public event EventHandler<BrowserExtendedNavigatingEventArgs> StartNavigate;
    /// <summary>
    /// Raised when a new window is to be created. Extends DWebBrowserEvents2::NewWindow2 with additional information about the new window.
    /// </summary>
    public event EventHandler<BrowserExtendedNavigatingEventArgs> StartNewWindow;
 
    /// <summary>
    /// Raises the <see cref="StartNewWindow"/> event
    /// </summary>
    /// <exception cref="ArgumentNullException">Thrown when BrowserExtendedNavigatingEventArgs is null</exception>
    protected void OnStartNewWindow(BrowserExtendedNavigatingEventArgs e)
    {
      if (e == null)
        throw new ArgumentNullException("e");

      if (this.StartNewWindow != null)
        this.StartNewWindow(this, e);

    }

    /// <summary>
    /// Raises the <see cref="StartNavigate"/> event
    /// </summary>
    /// <exception cref="ArgumentNullException">Thrown when BrowserExtendedNavigatingEventArgs is null</exception>
    protected void OnStartNavigate(BrowserExtendedNavigatingEventArgs e)
    {
      if (e == null)
        throw new ArgumentNullException("e");

      if (this.StartNavigate != null)
        this.StartNavigate(this, e);
    }

    #region The Implementation of DWebBrowserEvents2 for firing extra events

    //This class will capture events from the WebBrowser
    class WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2
    {
      public WebBrowserExtendedEvents() { }

      ExtendedWebBrowser _Browser;
      public WebBrowserExtendedEvents(ExtendedWebBrowser browser) { _Browser = browser; }

      #region DWebBrowserEvents2 Members

      //Implement whichever events you wish
      public void BeforeNavigate2(object pDisp, ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel)
      {
        Uri urlUri = new Uri(URL.ToString());

        string tFrame = null;
        if (targetFrameName != null)
          tFrame = targetFrameName.ToString();

        BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(pDisp, urlUri, tFrame, UrlContext.None);
        _Browser.OnStartNavigate(args);

        cancel = args.Cancel;
        pDisp = args.AutomationObject;
      }

      //The NewWindow2 event, used on Windows XP SP1 and below
      public void NewWindow2(ref object pDisp, ref bool cancel)
      {
        BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(pDisp, null, null, UrlContext.None);
        _Browser.OnStartNewWindow(args);
        cancel = args.Cancel;
        pDisp = args.AutomationObject;
      }
      
      // NewWindow3 event, used on Windows XP SP2 and higher
      public void NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)
      {
        BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(ppDisp, new Uri(bstrUrl), null, (UrlContext)dwFlags);
        _Browser.OnStartNewWindow(args);
        Cancel = args.Cancel;
        ppDisp = args.AutomationObject;
      }

      // Fired when downloading begins
      public void DownloadBegin()
      {
        _Browser.OnDownloading(EventArgs.Empty);
      }

      // Fired when downloading is completed
      public void DownloadComplete()
      {
        _Browser.OnDownloadComplete(EventArgs.Empty);
      }

      #region Unused events

      // This event doesn't fire. 
      [DispId(0x00000107)]
      public void WindowClosing(bool isChildWindow, ref bool cancel)
      {
      }

      public void OnQuit()
      {
        
      }

      public void StatusTextChange(string text)
      {
      }

      public void ProgressChange(int progress, int progressMax)
      {
      }

      public void TitleChange(string text)
      {
      }

      public void PropertyChange(string szProperty)
      {
      }

      public void NavigateComplete2(object pDisp, ref object URL)
      {
      }

      public void DocumentComplete(object pDisp, ref object URL)
      {
      }

      public void OnVisible(bool visible)
      {
      }

      public void OnToolBar(bool toolBar)
      {
      }

      public void OnMenuBar(bool menuBar)
      {
      }

      public void OnStatusBar(bool statusBar)
      {
      }

      public void OnFullScreen(bool fullScreen)
      {
      }

      public void OnTheaterMode(bool theaterMode)
      {
      }

      public void WindowSetResizable(bool resizable)
      {
      }

      public void WindowSetLeft(int left)
      {
      }

      public void WindowSetTop(int top)
      {
      }

      public void WindowSetWidth(int width)
      {
      }

      public void WindowSetHeight(int height)
      {
      }
      
      public void SetSecureLockIcon(int secureLockIcon)
      {
      }

      public void FileDownload(ref bool cancel)
      {
      }

      public void NavigateError(object pDisp, ref object URL, ref object frame, ref object statusCode, ref bool cancel)
      {
      }

      public void PrintTemplateInstantiation(object pDisp)
      {
      }

      public void PrintTemplateTeardown(object pDisp)
      {
      }

      public void UpdatePageStatus(object pDisp, ref object nPage, ref object fDone)
      {
      }

      public void PrivacyImpactedStateChange(bool bImpacted)
      {
      }

      public void CommandStateChange(int Command, bool Enable)
      {
      }

      public void ClientToHostWindow(ref int CX, ref int CY)
      {
      }
      #endregion

      #endregion
    }

    #endregion

    #region Raises the Quit event when the browser window is about to be destroyed

    /// <summary>
    /// Overridden
    /// </summary>
    /// <param name="m">The <see cref="Message"/> send to this procedure</param>
    [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")] 
    protected override void WndProc(ref Message m)
    {
      if (m.Msg == (int)WindowsMessages.WM_PARENTNOTIFY)
      {
        //int lp = m.LParam.ToInt32();
        int wp = m.WParam.ToInt32();

        int X = wp & 0xFFFF;
        //int Y = (wp >> 16) & 0xFFFF;
        if (X == (int)WindowsMessages.WM_DESTROY)
          this.OnQuit();
      }

      base.WndProc(ref m);
    }

    /// <summary>
    /// A list of all the available window messages
    /// </summary>
    enum WindowsMessages
    {
      WM_ACTIVATE = 0x6,
      WM_ACTIVATEAPP = 0x1C,
      WM_AFXFIRST = 0x360,
      WM_AFXLAST = 0x37F,
      WM_APP = 0x8000,
      WM_ASKCBFORMATNAME = 0x30C,
      WM_CANCELJOURNAL = 0x4B,
      WM_CANCELMODE = 0x1F,
      WM_CAPTURECHANGED = 0x215,
      WM_CHANGECBCHAIN = 0x30D,
      WM_CHAR = 0x102,
      WM_CHARTOITEM = 0x2F,
      WM_CHILDACTIVATE = 0x22,
      WM_CLEAR = 0x303,
      WM_CLOSE = 0x10,
      WM_COMMAND = 0x111,
      WM_COMPACTING = 0x41,
      WM_COMPAREITEM = 0x39,
      WM_CONTEXTMENU = 0x7B,
      WM_COPY = 0x301,
      WM_COPYDATA = 0x4A,
      WM_CREATE = 0x1,
      WM_CTLCOLORBTN = 0x135,
      WM_CTLCOLORDLG = 0x136,
      WM_CTLCOLOREDIT = 0x133,
      WM_CTLCOLORLISTBOX = 0x134,
      WM_CTLCOLORMSGBOX = 0x132,
      WM_CTLCOLORSCROLLBAR = 0x137,
      WM_CTLCOLORSTATIC = 0x138,
      WM_CUT = 0x300,
      WM_DEADCHAR = 0x103,
      WM_DELETEITEM = 0x2D,
      WM_DESTROY = 0x2,
      WM_DESTROYCLIPBOARD = 0x307,
      WM_DEVICECHANGE = 0x219,
      WM_DEVMODECHANGE = 0x1B,
      WM_DISPLAYCHANGE = 0x7E,
      WM_DRAWCLIPBOARD = 0x308,
      WM_DRAWITEM = 0x2B,
      WM_DROPFILES = 0x233,
      WM_ENABLE = 0xA,
      WM_ENDSESSION = 0x16,
      WM_ENTERIDLE = 0x121,
      WM_ENTERMENULOOP = 0x211,
      WM_ENTERSIZEMOVE = 0x231,
      WM_ERASEBKGND = 0x14,
      WM_EXITMENULOOP = 0x212,
      WM_EXITSIZEMOVE = 0x232,
      WM_FONTCHANGE = 0x1D,
      WM_GETDLGCODE = 0x87,
      WM_GETFONT = 0x31,
      WM_GETHOTKEY = 0x33,
      WM_GETICON = 0x7F,
      WM_GETMINMAXINFO = 0x24,
      WM_GETOBJECT = 0x3D,
      WM_GETTEXT = 0xD,
      WM_GETTEXTLENGTH = 0xE,
      WM_HANDHELDFIRST = 0x358,
      WM_HANDHELDLAST = 0x35F,
      WM_HELP = 0x53,
      WM_HOTKEY = 0x312,
      WM_HSCROLL = 0x114,
      WM_HSCROLLCLIPBOARD = 0x30E,
      WM_ICONERASEBKGND = 0x27,
      WM_IME_CHAR = 0x286,
      WM_IME_COMPOSITION = 0x10F,
      WM_IME_COMPOSITIONFULL = 0x284,
      WM_IME_CONTROL = 0x283,
      WM_IME_ENDCOMPOSITION = 0x10E,
      WM_IME_KEYDOWN = 0x290,
      WM_IME_KEYLAST = 0x10F,
      WM_IME_KEYUP = 0x291,
      WM_IME_NOTIFY = 0x282,
      WM_IME_REQUEST = 0x288,
      WM_IME_SELECT = 0x285,
      WM_IME_SETCONTEXT = 0x281,
      WM_IME_STARTCOMPOSITION = 0x10D,
      WM_INITDIALOG = 0x110,
      WM_INITMENU = 0x116,
      WM_INITMENUPOPUP = 0x117,
      WM_INPUTLANGCHANGE = 0x51,
      WM_INPUTLANGCHANGEREQUEST = 0x50,
      WM_KEYDOWN = 0x100,
      WM_KEYFIRST = 0x100,
      WM_KEYLAST = 0x108,
      WM_KEYUP = 0x101,
      WM_KILLFOCUS = 0x8,
      WM_LBUTTONDBLCLK = 0x203,
      WM_LBUTTONDOWN = 0x201,
      WM_LBUTTONUP = 0x202,
      WM_MBUTTONDBLCLK = 0x209,
      WM_MBUTTONDOWN = 0x207,
      WM_MBUTTONUP = 0x208,
      WM_MDIACTIVATE = 0x222,
      WM_MDICASCADE = 0x227,
      WM_MDICREATE = 0x220,
      WM_MDIDESTROY = 0x221,
      WM_MDIGETACTIVE = 0x229,
      WM_MDIICONARRANGE = 0x228,
      WM_MDIMAXIMIZE = 0x225,
      WM_MDINEXT = 0x224,
      WM_MDIREFRESHMENU = 0x234,
      WM_MDIRESTORE = 0x223,
      WM_MDISETMENU = 0x230,
      WM_MDITILE = 0x226,
      WM_MEASUREITEM = 0x2C,
      WM_MENUCHAR = 0x120,
      WM_MENUCOMMAND = 0x126,
      WM_MENUDRAG = 0x123,
      WM_MENUGETOBJECT = 0x124,
      WM_MENURBUTTONUP = 0x122,
      WM_MENUSELECT = 0x11F,
      WM_MOUSEACTIVATE = 0x21,
      WM_MOUSEFIRST = 0x200,
      WM_MOUSEHOVER = 0x2A1,
      WM_MOUSELAST = 0x20A,
      WM_MOUSELEAVE = 0x2A3,
      WM_MOUSEMOVE = 0x200,
      WM_MOUSEWHEEL = 0x20A,
      WM_MOVE = 0x3,
      WM_MOVING = 0x216,
      WM_NCACTIVATE = 0x86,
      WM_NCCALCSIZE = 0x83,
      WM_NCCREATE = 0x81,
      WM_NCDESTROY = 0x82,
      WM_NCHITTEST = 0x84,
      WM_NCLBUTTONDBLCLK = 0xA3,
      WM_NCLBUTTONDOWN = 0xA1,
      WM_NCLBUTTONUP = 0xA2,
      WM_NCMBUTTONDBLCLK = 0xA9,
      WM_NCMBUTTONDOWN = 0xA7,
      WM_NCMBUTTONUP = 0xA8,
      WM_NCMOUSEHOVER = 0x2A0,
      WM_NCMOUSELEAVE = 0x2A2,
      WM_NCMOUSEMOVE = 0xA0,
      WM_NCPAINT = 0x85,
      WM_NCRBUTTONDBLCLK = 0xA6,
      WM_NCRBUTTONDOWN = 0xA4,
      WM_NCRBUTTONUP = 0xA5,
      WM_NEXTDLGCTL = 0x28,
      WM_NEXTMENU = 0x213,
      WM_NOTIFY = 0x4E,
      WM_NOTIFYFORMAT = 0x55,
      WM_NULL = 0x0,
      WM_PAINT = 0xF,
      WM_PAINTCLIPBOARD = 0x309,
      WM_PAINTICON = 0x26,
      WM_PALETTECHANGED = 0x311,
      WM_PALETTEISCHANGING = 0x310,
      WM_PARENTNOTIFY = 0x210,
      WM_PASTE = 0x302,
      WM_PENWINFIRST = 0x380,
      WM_PENWINLAST = 0x38F,
      WM_POWER = 0x48,
      WM_PRINT = 0x317,
      WM_PRINTCLIENT = 0x318,
      WM_QUERYDRAGICON = 0x37,
      WM_QUERYENDSESSION = 0x11,
      WM_QUERYNEWPALETTE = 0x30F,
      WM_QUERYOPEN = 0x13,
      WM_QUEUESYNC = 0x23,
      WM_QUIT = 0x12,
      WM_RBUTTONDBLCLK = 0x206,
      WM_RBUTTONDOWN = 0x204,
      WM_RBUTTONUP = 0x205,
      WM_RENDERALLFORMATS = 0x306,
      WM_RENDERFORMAT = 0x305,
      WM_SETCURSOR = 0x20,
      WM_SETFOCUS = 0x7,
      WM_SETFONT = 0x30,
      WM_SETHOTKEY = 0x32,
      WM_SETICON = 0x80,
      WM_SETREDRAW = 0xB,
      WM_SETTEXT = 0xC,
      WM_SETTINGCHANGE = 0x1A,
      WM_SHOWWINDOW = 0x18,
      WM_SIZE = 0x5,
      WM_SIZECLIPBOARD = 0x30B,
      WM_SIZING = 0x214,
      WM_SPOOLERSTATUS = 0x2A,
      WM_STYLECHANGED = 0x7D,
      WM_STYLECHANGING = 0x7C,
      WM_SYNCPAINT = 0x88,
      WM_SYSCHAR = 0x106,
      WM_SYSCOLORCHANGE = 0x15,
      WM_SYSCOMMAND = 0x112,
      WM_SYSDEADCHAR = 0x107,
      WM_SYSKEYDOWN = 0x104,
      WM_SYSKEYUP = 0x105,
      WM_TCARD = 0x52,
      WM_TIMECHANGE = 0x1E,
      WM_TIMER = 0x113,
      WM_UNDO = 0x304,
      WM_UNINITMENUPOPUP = 0x125,
      WM_USER = 0x400,
      WM_USERCHANGED = 0x54,
      WM_VKEYTOITEM = 0x2E,
      WM_VSCROLL = 0x115,
      WM_VSCROLLCLIPBOARD = 0x30A,
      WM_WINDOWPOSCHANGED = 0x47,
      WM_WINDOWPOSCHANGING = 0x46,
      WM_WININICHANGE = 0x1A
    }

    /// <summary>
    /// Raises the <see cref="Quit"/> event
    /// </summary>
    protected void OnQuit()
    {
      EventHandler h = Quit;
      if (null != h)
        h(this, EventArgs.Empty);
    }

    /// <summary>
    /// Raised when the browser application quits
    /// </summary>
    /// <remarks>
    /// Do not confuse this with DWebBrowserEvents2.Quit... That's something else.
    /// </remarks>
    public event EventHandler Quit;


    #endregion
  }



}

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

Share

About the Author

Jeroen Landheer
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.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 29 Mar 2006
Article Copyright 2006 by Jeroen Landheer
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid