Click here to Skip to main content
15,891,828 members
Articles / Programming Languages / XML

[Obsolete] Image Capture Whole Web Page using C#

Rate me:
Please Sign up or sign in to vote.
4.74/5 (60 votes)
22 Jun 2005CPOL4 min read 938.7K   16.9K   234  
[Obsolete]Capture whole web pages as a single image using C#.
/* ---------------------------------------------------------------------------
 *
 * Copyright (c) Doug Weems.
 * 
 * You may use this code for fun and knowledge.
 * You can compile and use the application as is or copy out what you need.  
 * This code makes for a really useful tool.
 * 
 * ---------------------------------------------------------------------------
 */

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Drawing.Imaging;
using SHDocVw;
using mshtml;


namespace IEWindowCapture
{
	/// <summary>
	/// This is the working code for "IE Complete Web Window Image Capture".  IECWWIC for short.  
	/// Just kidding. ;-)  Call it, "WebPageToImage".
	/// This tool will pick up one open IE window and capture the entire web page to a single jpeg.
	/// It is best if you only are running the IE instance that you are interested in.
	/// The quality and size of the image can be adjusted and standard resolution screen sizes and web page name
	/// can be added to the image.
	/// Author:  Doug Weems
	/// </summary>
	public class frmMain : System.Windows.Forms.Form
	{
        private System.Windows.Forms.GroupBox grpWebCapture;
        private System.Windows.Forms.LinkLabel lnkOpenCapture;
        private System.Windows.Forms.CheckBox chkShowGuides;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.ComboBox cmbResolution;
        private System.Windows.Forms.Label lblResolution;
        private System.Windows.Forms.Label lblQuality;
        private System.Windows.Forms.ComboBox cmbQuality;
        private System.Windows.Forms.CheckBox chkWriteURL;
        private System.Windows.Forms.Button button1;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;



		public frmMain()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(frmMain));
            this.grpWebCapture = new System.Windows.Forms.GroupBox();
            this.lnkOpenCapture = new System.Windows.Forms.LinkLabel();
            this.chkShowGuides = new System.Windows.Forms.CheckBox();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.cmbResolution = new System.Windows.Forms.ComboBox();
            this.lblResolution = new System.Windows.Forms.Label();
            this.lblQuality = new System.Windows.Forms.Label();
            this.cmbQuality = new System.Windows.Forms.ComboBox();
            this.chkWriteURL = new System.Windows.Forms.CheckBox();
            this.button1 = new System.Windows.Forms.Button();
            this.grpWebCapture.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // grpWebCapture
            // 
            this.grpWebCapture.Controls.Add(this.lnkOpenCapture);
            this.grpWebCapture.Controls.Add(this.chkShowGuides);
            this.grpWebCapture.Controls.Add(this.groupBox1);
            this.grpWebCapture.Controls.Add(this.chkWriteURL);
            this.grpWebCapture.Controls.Add(this.button1);
            this.grpWebCapture.Location = new System.Drawing.Point(28, 12);
            this.grpWebCapture.Name = "grpWebCapture";
            this.grpWebCapture.Size = new System.Drawing.Size(256, 208);
            this.grpWebCapture.TabIndex = 41;
            this.grpWebCapture.TabStop = false;
            this.grpWebCapture.Text = "Capture Web Page";
            // 
            // lnkOpenCapture
            // 
            this.lnkOpenCapture.Location = new System.Drawing.Point(16, 136);
            this.lnkOpenCapture.Name = "lnkOpenCapture";
            this.lnkOpenCapture.Size = new System.Drawing.Size(128, 16);
            this.lnkOpenCapture.TabIndex = 36;
            this.lnkOpenCapture.TabStop = true;
            this.lnkOpenCapture.Text = "Open Capture Directory";
            this.lnkOpenCapture.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkOpenCapture_LinkClicked);
            // 
            // chkShowGuides
            // 
            this.chkShowGuides.Location = new System.Drawing.Point(16, 112);
            this.chkShowGuides.Name = "chkShowGuides";
            this.chkShowGuides.Size = new System.Drawing.Size(200, 16);
            this.chkShowGuides.TabIndex = 34;
            this.chkShowGuides.Text = "draw Standard Resolution Guides";
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.cmbResolution);
            this.groupBox1.Controls.Add(this.lblResolution);
            this.groupBox1.Controls.Add(this.lblQuality);
            this.groupBox1.Controls.Add(this.cmbQuality);
            this.groupBox1.ForeColor = System.Drawing.Color.Black;
            this.groupBox1.Location = new System.Drawing.Point(16, 16);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(200, 80);
            this.groupBox1.TabIndex = 39;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Reduce File Size by reducing Quality and/or Resolution";
            // 
            // cmbResolution
            // 
            this.cmbResolution.Items.AddRange(new object[] {
                                                               "100",
                                                               "90",
                                                               "80",
                                                               "70",
                                                               "60",
                                                               "50",
                                                               "40"});
            this.cmbResolution.Location = new System.Drawing.Point(120, 32);
            this.cmbResolution.Name = "cmbResolution";
            this.cmbResolution.Size = new System.Drawing.Size(48, 21);
            this.cmbResolution.TabIndex = 31;
            this.cmbResolution.Text = "90";
            // 
            // lblResolution
            // 
            this.lblResolution.Location = new System.Drawing.Point(24, 32);
            this.lblResolution.Name = "lblResolution";
            this.lblResolution.Size = new System.Drawing.Size(88, 16);
            this.lblResolution.TabIndex = 35;
            this.lblResolution.Text = "% Capture Size";
            this.lblResolution.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // lblQuality
            // 
            this.lblQuality.Location = new System.Drawing.Point(24, 56);
            this.lblQuality.Name = "lblQuality";
            this.lblQuality.Size = new System.Drawing.Size(88, 16);
            this.lblQuality.TabIndex = 38;
            this.lblQuality.Text = "Quality";
            this.lblQuality.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // cmbQuality
            // 
            this.cmbQuality.Items.AddRange(new object[] {
                                                            "100",
                                                            "90",
                                                            "80",
                                                            "70",
                                                            "50",
                                                            "30",
                                                            "10"});
            this.cmbQuality.Location = new System.Drawing.Point(120, 56);
            this.cmbQuality.Name = "cmbQuality";
            this.cmbQuality.Size = new System.Drawing.Size(48, 21);
            this.cmbQuality.TabIndex = 37;
            this.cmbQuality.Text = "70";
            // 
            // chkWriteURL
            // 
            this.chkWriteURL.Location = new System.Drawing.Point(16, 96);
            this.chkWriteURL.Name = "chkWriteURL";
            this.chkWriteURL.Size = new System.Drawing.Size(176, 16);
            this.chkWriteURL.TabIndex = 32;
            this.chkWriteURL.Text = "write URL name on Image";
            // 
            // button1
            // 
            this.button1.Cursor = System.Windows.Forms.Cursors.Hand;
            this.button1.ForeColor = System.Drawing.Color.White;
            this.button1.Image = ((System.Drawing.Image)(resources.GetObject("button1.Image")));
            this.button1.Location = new System.Drawing.Point(176, 144);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(48, 40);
            this.button1.TabIndex = 29;
            this.button1.TextAlign = System.Drawing.ContentAlignment.TopCenter;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // frmMain
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(304, 238);
            this.Controls.Add(this.grpWebCapture);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "frmMain";
            this.Text = "Capture";
            this.grpWebCapture.ResumeLayout(false);
            this.groupBox1.ResumeLayout(false);
            this.ResumeLayout(false);

        }
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new frmMain());
		}


        //We need some system dll functions.
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/, IntPtr next /*HWND*/, string sClassName, IntPtr sWindowTitle);
        
        [DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)] 
        public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd); 

        [DllImport("user32.Dll")]
        public static extern void GetClassName(int h, StringBuilder s, int nMaxCount);

        [DllImport("user32.dll")]
        private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);

        public const int GW_CHILD = 5; 
        public const int GW_HWNDNEXT = 2;

        private void button1_Click(object sender, System.EventArgs e)
        {
            //TODO In Next Version:
            //Add cursor capture
            //Add file naming option
            //Add visible screen capture
            //Make captured image a DDB not a DIB bitmap.
            
            Cursor.Current = Cursors.WaitCursor;
        
            SHDocVw.WebBrowser m_browser = null;

            SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindowsClass();
 
            //Find first availble browser window.
            //Application can easily be modified to loop through and capture all open windows.
            string filename;
            foreach (SHDocVw.WebBrowser ie in shellWindows)
            {
                filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
    
                if (filename.Equals("iexplore"))
                {
                    m_browser = ie;
                    break;  
                }
            }
            if (m_browser == null)
            {   
                MessageBox.Show("No Browser Open");
                return;
            }

            //Assign Browser Document
            mshtml.IHTMLDocument2 myDoc = (mshtml.IHTMLDocument2)m_browser.Document;

            
            //URL Location
            string myLocalLink = myDoc.url;
            int URLExtraHeight = 0;
            int URLExtraLeft = 0;

            //Adjustment variable for capture size.
            if (chkWriteURL.Checked == true)
                URLExtraHeight = 25;

            //TrimHeight and TrimLeft trims off some captured IE graphics.
            int trimHeight = 3;
            int trimLeft = 3;

            //Use UrlExtra height to carry trimHeight.
            URLExtraHeight = URLExtraHeight - trimHeight;
            URLExtraLeft = URLExtraLeft - trimLeft;

            myDoc.body.setAttribute("scroll", "yes", 0);

            //Get Browser Window Height
            int heightsize = (int)myDoc.body.getAttribute("scrollHeight", 0);
            int widthsize = (int)myDoc.body.getAttribute("scrollWidth", 0);
            
            //Get Screen Height
            int screenHeight = (int)myDoc.body.getAttribute("clientHeight", 0);
            int screenWidth = (int)myDoc.body.getAttribute("clientWidth", 0);

            //Get bitmap to hold screen fragment.
            Bitmap bm = new Bitmap(screenWidth, screenHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);

            //Create a target bitmap to draw into.
            Bitmap bm2 = new Bitmap(widthsize + URLExtraLeft, heightsize + URLExtraHeight - trimHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
            Graphics g2 = Graphics.FromImage(bm2);

            Graphics g = null;
            IntPtr hdc;
            Image screenfrag = null;
            int brwTop = 0;
            int brwLeft = 0;
            int myPage = 0;
            IntPtr myIntptr = (IntPtr)m_browser.HWND;
            //Get inner browser window.
            int hwndInt = myIntptr.ToInt32();
            IntPtr hwnd = myIntptr;
            hwnd = GetWindow(hwnd, GW_CHILD); 
            StringBuilder sbc = new StringBuilder(256);
            //Get Browser "Document" Handle
            while (hwndInt != 0) 
            { 
                hwndInt = hwnd.ToInt32();
                GetClassName(hwndInt, sbc, 256);

                if(sbc.ToString().IndexOf("Shell DocObject View", 0) > -1)
                {
                    hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero);
                    break;
                }                
                hwnd = GetWindow(hwnd, GW_HWNDNEXT);

            } 
            
            //Get Screen Height (for bottom up screen drawing)
            while ((myPage * screenHeight) < heightsize)
            {
                myDoc.body.setAttribute("scrollTop", (screenHeight - 5) * myPage, 0);
                ++myPage;
            }
            //Rollback the page count by one
            --myPage;
            
            int myPageWidth = 0;

            while ((myPageWidth * screenWidth) < widthsize)
            {
                myDoc.body.setAttribute("scrollLeft", (screenWidth - 5) * myPageWidth, 0);
                brwLeft = (int)myDoc.body.getAttribute("scrollLeft", 0);
                for (int i = myPage; i >= 0; --i)
                {
                    //Shoot visible window
                    g = Graphics.FromImage(bm);
                    hdc = g.GetHdc();
                    myDoc.body.setAttribute("scrollTop", (screenHeight - 5) * i, 0);
                    brwTop = (int)myDoc.body.getAttribute("scrollTop", 0);
                    PrintWindow(hwnd, hdc, 0);
                    g.ReleaseHdc(hdc);
                    g.Flush();
                    screenfrag = Image.FromHbitmap(bm.GetHbitmap());
                    g2.DrawImage(screenfrag, brwLeft + URLExtraLeft, brwTop + URLExtraHeight);
                }
                ++myPageWidth;
            }

            //Draw Standard Resolution Guides
            if(chkShowGuides.Checked == true)
            {
                // Create pen.
                int myWidth = 1;
                Pen myPen = new Pen(Color.Navy, myWidth);
                Pen myShadowPen = new Pen(Color.NavajoWhite, myWidth);
                // Create coordinates of points that define line.
                float x1 = -(float)myWidth - 1 + URLExtraLeft;
                float y1 = -(float)myWidth - 1 + URLExtraHeight;

                float x600 = 600.0F + (float)myWidth+1;
                float y480 = 480.0F + (float)myWidth+1;

                float x2 = 800.0F + (float)myWidth+1;
                float y2 = 600.0F + (float)myWidth+1;

                float x3 = 1024.0F + (float)myWidth+1;
                float y3 = 768.0F + (float)myWidth+1;

                float x1280 = 1280.0F + (float)myWidth+1;
                float y1024 = 1024.0F + (float)myWidth+1;

                // Draw line to screen.
                g2.DrawRectangle(myPen, x1, y1, x600+myWidth, y480+myWidth);
                g2.DrawRectangle(myPen, x1, y1, x2+myWidth, y2+myWidth);
                g2.DrawRectangle(myPen, x1, y1, x3+myWidth, y3+myWidth);
                g2.DrawRectangle(myPen, x1, y1, x1280+myWidth, y1024+myWidth);

                // Create font and brush.
                Font drawFont = new Font("Arial", 12);
                SolidBrush drawBrush = new SolidBrush(Color.Navy);
                SolidBrush drawBrush2 = new SolidBrush(Color.NavajoWhite);
                
                // Set format of string.
                StringFormat drawFormat = new StringFormat();
                drawFormat.FormatFlags = StringFormatFlags.FitBlackBox;
                // Draw string to screen.
                g2.DrawString("600 x 480", drawFont, drawBrush, 5, y480 - 20 + URLExtraHeight, drawFormat);
                g2.DrawString("800 x 600", drawFont, drawBrush, 5, y2 - 20 + URLExtraHeight, drawFormat);
                g2.DrawString("1024 x 768", drawFont, drawBrush, 5, y3 - 20 + URLExtraHeight, drawFormat);
                g2.DrawString("1280 x 1024", drawFont, drawBrush, 5, y1024 - 20 + URLExtraHeight, drawFormat);
            }

            //Write URL
            if (chkWriteURL.Checked == true)
            {   //Backfill URL paint location
                SolidBrush whiteBrush = new SolidBrush(Color.White);
                Rectangle fillRect = new Rectangle(0, 0, widthsize, URLExtraHeight+2);
                Region fillRegion = new Region(fillRect);
                g2.FillRegion(whiteBrush, fillRegion);

                SolidBrush drawBrushURL = new SolidBrush(Color.Black);
                Font drawFont = new Font("Arial", 12);
                StringFormat drawFormat = new StringFormat();
                drawFormat.FormatFlags = StringFormatFlags.FitBlackBox;

                g2.DrawString(myLocalLink, drawFont, drawBrushURL, 0, 0, drawFormat);
            }
            
            //Reduce Resolution Size
            double myResolution = Convert.ToDouble(cmbResolution.Text) * 0.01;
            int finalWidth = (int)((widthsize + URLExtraLeft) * myResolution);
            int finalHeight = (int)((heightsize + URLExtraHeight) * myResolution);
            Bitmap finalImage = new Bitmap(finalWidth, finalHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
            Graphics gFinal = Graphics.FromImage((Image)finalImage);
            gFinal.DrawImage( bm2, 0, 0, finalWidth, finalHeight);
  
            //Get Time Stamp
            DateTime myTime = DateTime.Now;
            String format = "MM.dd.hh.mm.ss";

            //Create Directory to save image to.
            Directory.CreateDirectory("C:\\IECapture");

            //Write Image.
            EncoderParameters eps = new EncoderParameters(1);
            long myQuality = Convert.ToInt64(cmbQuality.Text);
            eps.Param[0] = new EncoderParameter( System.Drawing.Imaging.Encoder.Quality, myQuality);
            ImageCodecInfo ici = GetEncoderInfo("image/jpeg");
            finalImage.Save(@"c:\\IECapture\Captured_" + myTime.ToString(format) + ".jpg", ici, eps);


            //Clean Up.
            myDoc = null;
            g.Dispose();
            g2.Dispose();
            gFinal.Dispose();
            bm.Dispose();
            bm2.Dispose();
            finalImage.Dispose();

            Cursor.Current = Cursors.Default;
        }

        private static ImageCodecInfo GetEncoderInfo(String mimeType)
        {
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for(j = 0; j < encoders.Length; ++j)
            {
                if(encoders[j].MimeType == mimeType)
                    return encoders[j];
            }
            return null;
        }

        private void lnkOpenCapture_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("explorer.exe", "C:\\IECapture");
        }



	}
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
My experience with programming began with Turbo Pascal while working on my Physics degree back in 1989.

After getting out of school, I used pre-VBA Excel macros to write some really fancy applications to help with the job I was doing. This inspired me to try to write "Windows" programs and to search out Visual Basic 3.0.

I wrote a bunch of small applications and ran them against Access and FoxPro. However, this still wasn't my primary job.

In 1994, I went on my first contract, a 3-month deal that turned into 3-years. I learned a lot more about development. Development was in VB3, VB4 and ASP. I got a chance to admin NT4 and SQL Server 6 and 6.5.

After moving on to another company, I spent another 2 years with VB and then 5 years with Java and JSP.

In March of 2004, I installed Visual Studio 2003. I tasted C#, and became hopelessly addicted.

My other interests are my 3 sons, my wife Smile | :) , metal detecting, yard work, travel and learning new things.

update: Now love SharePoint, PowerShell, JQuery, C#, PHP

location: Atlanta, Georgia

Comments and Discussions