Custom WebBrowser Control with Zooming and CSS Injection

I thought I would post this custom browser I wrote for a project I am working on. It allows you to access the zoom function of the Internet Explorer browser (AxWebBrowser) by calling a Zoom method (passing in a whole number, expressed as percentage). I also added an InjectCSS() method which allows you to insert some extra CSS into the page (after it is loaded). I used this in a project recently where I didn’t want to mess with my generated page CSS or HTML, but simple wanted to add a couple of styles for display only purposes.

    public partial class CustomBrowser : WebBrowser
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern short GetAsyncKeyState(int keyCode);
        public bool IsKeyDown(Keys key)
        {
            return (GetAsyncKeyState((int)key) & 0x8000) != 0;
        }
 
        #region enums
        public enum OLECMDID
        {
            // ...
            OLECMDID_OPTICAL_ZOOM = 63,
            OLECMDID_OPTICAL_GETZOOMRANGE = 64,
            // ...
        }
 
        public enum OLECMDEXECOPT
        {
            // ...
            OLECMDEXECOPT_DONTPROMPTUSER,
            // ...
        }
 
        public enum OLECMDF
        {
            // ...
            OLECMDF_SUPPORTED = 1
        }
        #endregion
 
        #region IWebBrowser2
        [ComImport, /*SuppressUnmanagedCodeSecurity,*/
         TypeLibType(TypeLibTypeFlags.FOleAutomation |
                     TypeLibTypeFlags.FDual |
                     TypeLibTypeFlags.FHidden),
         Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")]
        public interface IWebBrowser2
        {
            [DispId(100)]
            void GoBack();
            [DispId(0x65)]
            void GoForward();
            [DispId(0x66)]
            void GoHome();
            [DispId(0x67)]
            void GoSearch();
            [DispId(0x68)]
            void Navigate([In] string Url,
                          [In] ref object flags,
                          [In] ref object targetFrameName,
                          [In] ref object postData,
                          [In] ref object headers);
            [DispId(-550)]
            void Refresh();
            [DispId(0x69)]
            void Refresh2([In] ref object level);
            [DispId(0x6a)]
            void Stop();
            [DispId(200)]
            object Application
            {
                [return:
                 MarshalAs(UnmanagedType.IDispatch)]
                get;
            }
            [DispId(0xc9)]
            object Parent
            {
                [return:
                 MarshalAs(UnmanagedType.IDispatch)]
                get;
            }
            [DispId(0xca)]
            object Container
            {
                [return:
                 MarshalAs(UnmanagedType.IDispatch)]
                get;
            }
            [DispId(0xcb)]
            object Document
            {
                [return:
                 MarshalAs(UnmanagedType.IDispatch)]
                get;
            }
            [DispId(0xcc)]
            bool TopLevelContainer { get; }
            [DispId(0xcd)]
            string Type { get; }
            [DispId(0xce)]
            int Left { get; set; }
            [DispId(0xcf)]
            int Top { get; set; }
            [DispId(0xd0)]
            int Width { get; set; }
            [DispId(0xd1)]
            int Height { get; set; }
            [DispId(210)]
            string LocationName { get; }
            [DispId(0xd3)]
            string LocationURL { get; }
            [DispId(0xd4)]
            bool Busy { get; }
            [DispId(300)]
            void Quit();
            [DispId(0x12d)]
            void ClientToWindow(out int pcx, out int pcy);
            [DispId(0x12e)]
            void PutProperty([In] string property,
                             [In] object vtValue);
            [DispId(0x12f)]
            object GetProperty([In] string property);
            [DispId(0)]
            string Name { get; }
            [DispId(-515)]
            int HWND { get; }
            [DispId(400)]
            string FullName { get; }
            [DispId(0x191)]
            string Path { get; }
            [DispId(0x192)]
            bool Visible { get; set; }
            [DispId(0x193)]
            bool StatusBar { get; set; }
            [DispId(0x194)]
            string StatusText { get; set; }
            [DispId(0x195)]
            int ToolBar { get; set; }
            [DispId(0x196)]
            bool MenuBar { get; set; }
            [DispId(0x197)]
            bool FullScreen { get; set; }
            [DispId(500)]
            void Navigate2([In] ref object URL,
                           [In] ref object flags,
                           [In] ref object targetFrameName,
                           [In] ref object postData,
                           [In] ref object headers);
            [DispId(0x1f5)]
            OLECMDF QueryStatusWB([In] OLECMDID cmdID);
            [DispId(0x1f6)]
            void ExecWB([In] OLECMDID cmdID,
                        [In] OLECMDEXECOPT cmdexecopt,
                        ref object pvaIn, IntPtr pvaOut);
            [DispId(0x1f7)]
            void ShowBrowserBar([In] ref object pvaClsid,
                                [In] ref object pvarShow,
                                [In] ref object pvarSize);
            [DispId(-525)]
            WebBrowserReadyState ReadyState { get; }
            [DispId(550)]
            bool Offline { get; set; }
            [DispId(0x227)]
            bool Silent { get; set; }
            [DispId(0x228)]
            bool RegisterAsBrowser { get; set; }
            [DispId(0x229)]
            bool RegisterAsDropTarget { get; set; }
            [DispId(0x22a)]
            bool TheaterMode { get; set; }
            [DispId(0x22b)]
            bool AddressBar { get; set; }
            [DispId(0x22c)]
            bool Resizable { get; set; }
        }
        #endregion
 
        private IWebBrowser2 axIWebBrowser2;
 
        public CustomBrowser()
        {
        }
 
        ~CustomBrowser()
        {
        }
 
        protected override void AttachInterfaces(
            object nativeActiveXObject)
        {
            base.AttachInterfaces(nativeActiveXObject);
            this.axIWebBrowser2 = (IWebBrowser2)nativeActiveXObject;
        }
 
        protected override void DetachInterfaces()
        {
            base.DetachInterfaces();
            this.axIWebBrowser2 = null;
        }
 
        protected override void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
        {
            base.OnDocumentCompleted(e);
        }
 
        public void InjectCSS()
        {
            try
            {
                mshtml.HTMLDocument test = (mshtml.HTMLDocument)this.Document.DomDocument;
                //inject CSS
                if (test.styleSheets.length < 31)
                { // createStyleSheet throws "Invalid Argument if >31 stylesheets on page
 
                    mshtml.IHTMLStyleSheet css = (mshtml.IHTMLStyleSheet)test.createStyleSheet("", 0);
                    css.cssText = "//Insert Custom CSS here!";
                    // CSS should now affect page
                }
                else
                {
                    System.Console.WriteLine("Could not inject CSS due to styleSheets.length greater than 31");
                    return;
                }
            }
            catch { }
        }
 
        int currentZoom = 100;
        public void Zoom(int factor)
        {
            object pvaIn = factor;
            try
            {
                this.axIWebBrowser2.ExecWB(OLECMDID.OLECMDID_OPTICAL_ZOOM,
                   OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
                   ref pvaIn, 
                   IntPtr.Zero);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }