Click here to Skip to main content
15,886,806 members
Articles / Programming Languages / C#

How to capture a Window as an Image and save it

Rate me:
Please Sign up or sign in to vote.
4.43/5 (12 votes)
15 Jun 2007CPOL3 min read 142.9K   6.4K   91  
Take a snapshot of the main Window of any UI application
/*
 * Please leave this Copyright notice in your code if you use it
 * Written by Decebal Mihailescu [http://www.codeproject.com/script/articles/list_articles.asp?userid=634640]
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;

namespace SnapShot
{

    public partial class LocalSnapShotForm : Form
    {

        private IntPtr _hwnd = IntPtr.Zero;
        private UIApps _Apps;
        private const Int32 IDM_ABOUT  = 5000;

        private Image GetScreenShot( Point location, Size size)
        {
            IntPtr windowHandle = Win32API.GetDesktopWindow();
            Image myImage = new Bitmap(size.Width, size.Height);
            Graphics g = Graphics.FromImage(myImage);
            IntPtr destDeviceContext = g.GetHdc();
            IntPtr srcDeviceContext = Win32API.GetWindowDC(windowHandle);
            Win32API.BitBlt(destDeviceContext, 0, 0, size.Width, size.Height, srcDeviceContext, location.X, location.Y, Win32API.SRCCOPY);
            Win32API.ReleaseDC(windowHandle, srcDeviceContext);
            g.ReleaseHdc(destDeviceContext);
            return myImage;
        }

        private static Bitmap MakeSnapshot(IntPtr AppWndHandle, bool IsClientWnd, Win32API.WindowShowStyle nCmdShow)
        {

            if (AppWndHandle == IntPtr.Zero || !Win32API.IsWindow(AppWndHandle) || !Win32API.IsWindowVisible(AppWndHandle))
                return null;
            if(Win32API.IsIconic(AppWndHandle))
                Win32API.ShowWindow(AppWndHandle,nCmdShow);//show it
            if(!Win32API.SetForegroundWindow(AppWndHandle))
                    return null;//can't bring it to front
            System.Threading.Thread.Sleep(1000);//give it some time to redraw
            RECT appRect;
            bool res = IsClientWnd ? Win32API.GetClientRect(AppWndHandle, out appRect): Win32API.GetWindowRect(AppWndHandle, out appRect);
            if (!res || appRect.Height == 0 || appRect.Width == 0)
            {
                return null;//some hidden window
            }
            if(IsClientWnd)
            {
                Point lt = new Point(appRect.Left, appRect.Top);
                Point rb = new Point(appRect.Right, appRect.Bottom);
                Win32API.ClientToScreen(AppWndHandle,ref lt);
                Win32API.ClientToScreen(AppWndHandle,ref rb);
                appRect.Left = lt.X;
                appRect.Top = lt.Y;
                appRect.Right = rb.X;
                appRect.Bottom = rb.Y;
            }
            //Intersect with the Desktop rectangle and get what's visible
            IntPtr DesktopHandle = Win32API.GetDesktopWindow();
            RECT desktopRect;
            Win32API.GetWindowRect(DesktopHandle, out desktopRect);
            RECT visibleRect;
            if (!Win32API.IntersectRect(out visibleRect, ref desktopRect, ref appRect))
            {
                visibleRect = appRect;
            }
            if(Win32API.IsRectEmpty(ref visibleRect))
                return null;

            int Width = visibleRect.Width;
            int Height = visibleRect.Height;
            IntPtr hdcTo = IntPtr.Zero;
            IntPtr hdcFrom = IntPtr.Zero;
            IntPtr hBitmap = IntPtr.Zero;
            try
            {
                Bitmap clsRet = null;

                // get device context of the window...
                hdcFrom = IsClientWnd ? Win32API.GetDC(AppWndHandle) : Win32API.GetWindowDC(AppWndHandle);

                // create dc that we can draw to...
                hdcTo = Win32API.CreateCompatibleDC(hdcFrom);
                hBitmap = Win32API.CreateCompatibleBitmap(hdcFrom, Width, Height);

                //  validate...
                if (hBitmap != IntPtr.Zero)
                {
                    // copy...
                    int x = appRect.Left < 0 ? -appRect.Left : 0;
                    int y = appRect.Top < 0 ? -appRect.Top : 0;
                    IntPtr hLocalBitmap = Win32API.SelectObject(hdcTo, hBitmap);
                    Win32API.BitBlt(hdcTo, 0, 0, Width, Height, hdcFrom, x, y, Win32API.SRCCOPY);
                    Win32API.SelectObject(hdcTo, hLocalBitmap);
                    //  create bitmap for window image...
                    clsRet = System.Drawing.Image.FromHbitmap(hBitmap);
                }
                //MessageBox.Show(string.Format("rect ={0} \n deskrect ={1} \n visiblerect = {2}",rct,drct,VisibleRCT));
                //  return...
                return clsRet;
            }
            finally
            {
                //  release ...
                if (hdcFrom != IntPtr.Zero)
                    Win32API.ReleaseDC(AppWndHandle, hdcFrom);
                if(hdcTo != IntPtr.Zero)
                    Win32API.DeleteDC(hdcTo);
                if (hBitmap != IntPtr.Zero)
                    Win32API.DeleteObject(hBitmap);
            }


        }

        public LocalSnapShotForm()
        {
            InitializeComponent();
        }

        private void btnSnapShot_Click(object sender, EventArgs e)
        {
            Bitmap bitmap = MakeSnapshot(_hwnd, this.ckbClientWnd.Checked, Win32API.WindowShowStyle.Restore);
            if (bitmap != null)
                _pictureBox.Image = bitmap;
            else
            {
                lblHwnd.Text = "Hwnd:";
                btnSnapSot.Enabled = false;
            }
            btnSaveImage.Enabled = _pictureBox.Image != null;
            Win32API.SetForegroundWindow(this.Handle);
        }

        private void btnSaveImage_Click(object sender, EventArgs e)
        {
            if(saveFileDialog1.ShowDialog()!=DialogResult.Cancel) 
            {
                try
                {
                    string ext = System.IO.Path.GetExtension(saveFileDialog1.FileName).Substring(1).ToLower();
                    switch (ext)
                    {
                        case "jpg":
                        case "jpeg":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Jpeg);
                            break;
                        case "bmp":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Bmp);
                            break;
                        case "gif":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Gif);
                            break;
                        case "emf":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Emf);
                            break;
                        case "ico":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Icon);
                            break;
                        case "png":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Png);
                            break;
                        case "tif":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Tiff);
                            break;
                        case "wmf":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Wmf);
                            break;
                        case "exif":
                            _pictureBox.Image.Save(saveFileDialog1.FileName, ImageFormat.Exif);
                            break;
                        default:
                            MessageBox.Show(this, "Unknown format.Select a known one.", "Conversion error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, "Image Conversion error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

        }

        private void LocalSnapShotForm_Load(object sender, EventArgs e)
        {
            saveFileDialog1.AddExtension = true;
            saveFileDialog1.Filter = "Img(.bmp;.jpg;.jpeg;.gif;.emf;.ico;.png;.tif;.wmf;.exif)|*.BMP;*.JPG;*.jpeg;*.GIF;*.emf;*.ico;*.png;*.tif;*.wmf;*.exif|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 1;
            IntPtr sysMenuHandle = Win32API.GetSystemMenu(this.Handle, false);
            Win32API.AppendMenu(sysMenuHandle, Win32API.MF_SEPARATOR, 0, string.Empty);
            Win32API.AppendMenu(sysMenuHandle, Win32API.MF_STRING, IDM_ABOUT, "About SnapShot...");
        }


        private void LocalSnapShotForm_Shown(object sender, EventArgs e)
        {
            _Apps = new UIApps(System.Diagnostics.Process.GetProcesses());
            cmbProcs.BeginUpdate();
            cmbProcs.DataSource = _Apps;
            cmbProcs.DisplayMember = "Description";
            cmbProcs.EndUpdate();
        }

        private void btnFindWnd_Click(object sender, EventArgs e)
        {
            _hwnd = Win32API.FindWindow((textBoxClass.Text.Length > 0) ? textBoxClass.Text : null,
                (textBoxCaption.Text.Length > 0)?textBoxCaption.Text:null);
            btnSnapSot.Enabled = false;
            if (_hwnd != IntPtr.Zero)
            {
                RECT rct;
                bool res = ckbClientWnd.Checked ? Win32API.GetWindowRect(_hwnd, out rct) : Win32API.GetClientRect(_hwnd, out rct);
                if (!res)
                {
                    MessageBox.Show("Can't get the window rectangle");
                }
                else
                {
                    btnSnapSot.Enabled = true;
                }
                lblHwnd.Text = string.Format("Hwnd: {0:X}", (int)_hwnd);
            }
            else
            {
                lblHwnd.Text = "Hwnd:";
                MessageBox.Show(string.Format("No window with class = '{0}' & Caption = '{1}'", textBoxClass.Text, textBoxCaption.Text));
            }
        }

        private void textBox_TextChanged(object sender, EventArgs e)
        {
            btn_FindWnd.Enabled = textBoxCaption.Text.Length > 0 || textBoxClass.Text.Length > 0;
        }

        private void cmbProcs_SelectedIndexChanged(object sender, EventArgs e)
        {
            int ind = 0;
            ComboBox cb = sender as ComboBox;
            ind = cb.SelectedIndex;
            _hwnd = _Apps[ind].HWnd;
            btnSnapSot.Enabled = _hwnd != IntPtr.Zero;
            textBoxCaption.Text = _Apps[ind].Caption;
            textBoxClass.Text = _Apps[ind].WindowClass;
            lblHwnd.Text = string.Format("Hwnd: {0:X}", (int)_hwnd);
            btn_FindWnd.Enabled = false;
        }

        internal delegate void AboutHandler();
        protected override void WndProc(ref Message m)
        {
				switch(m.WParam.ToInt32())
				{
                    case IDM_ABOUT:
                        {
                            AboutHandler hnd = delegate()
                            {
                                AboutUtil.About dlg = new AboutUtil.About(this);
                                dlg.ShowDialog();
                                dlg.Dispose();
                            };
                            BeginInvoke(hnd);
                        }

                        break;
					default:
						break;
				} 
            base.WndProc(ref m);
        }
    }
}
//  HDC hDC,                  // Handle to the display device context 
//      hDCMem;               // Handle to the memory device context
//  HBITMAP hBitmap;          // Handle to the new bitmap
//  int iWidth, iHeight;      // Width and height of the bitmap
//  // Retrieve the handle to a display device context for the client 
//  // area of the window. 
//  hDC = GetDC (hwnd);
//  // Create a memory device context compatible with the device. 
//  hDCMem = CreateCompatibleDC (hDC);
//  // Retrieve the width and height of window display elements.
//  iWidth = GetSystemMetrics (SM_CXSCREEN) / 10;
//  iHeight = GetSystemMetrics (SM_CYSCREEN) / 10;
//  // Create a bitmap compatible with the device associated with the 
//  // device context.
//  hBitmap = CreateCompatibleBitmap (hDC, iWidth, iHeight);
//// Insert code to use the bitmap.
//  // Delete the bitmap object and free all resources associated with it. 
//  DeleteObject (hBitmap);
//  // Delete the memory device context and the display device context.
//  DeleteDC (hDCMem);
//  DeleteDC (hDC);

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
Software Developer (Senior)
United States United States
Decebal Mihailescu is a software engineer with interest in .Net, C# and C++.

Comments and Discussions