Capturing the Screen Image Using C#

Environment: C#, .NetFramework, Windows9x, Windows2000, WindowsXP

I am working on a desktop-sharing type application in C#. The first problem that I encountered was that there was not much in C# to capture the desktop image. After a bit of research, I came to know that I shall have to use the Win32 APIs to provide this functionality to my application. I made the following three classes to perform this job:

Class Description
PlatformInvokeGDI32 All the GDI32.dll APIs being used in this application are placed in this class.
PlatformInvokeUSER32 All the User32.dll APIs have been placed in this class.
CaptureScreen In this class I have provided a simple static function, GetDesktoImage, that captures the screen image using the APIs given in PlatformInvokeGDI32 and PlatformInvokeUSER32 and returns it as a bitmap.

You can very easily place these classes in your C# application. Just copy and paste the following code into your C# project without changing anything at all. If you want to use the accompanying source files, either you will add the CaptureScreen namespace in your project or just change the CaptureScreen namespace in these classes with your project namespace; that's all.

Here Is the Beautiful Source Code

///
/// This class shall keep the GDI32 APIs used in our program.
///
public class PlatformInvokeGDI32
{
#region Class Variables
public  const int SRCCOPY = 13369376;
#endregion
#region Class Functions
[DllImport("gdi32.dll",EntryPoint="DeleteDC")] public static extern IntPtr DeleteDC(IntPtr hDc); [DllImport("gdi32.dll",EntryPoint="DeleteObject")] public static extern IntPtr DeleteObject(IntPtr hDc); [DllImport("gdi32.dll",EntryPoint="BitBlt")] public static extern bool BitBlt(IntPtr hdcDest,int xDest, int yDest,int wDest, int hDest,IntPtr hdcSource, int xSrc,int ySrc,int RasterOp); [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")] public static extern IntPtr CreateCompatibleBitmap (IntPtr hdc,int nWidth, int nHeight); [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport ("gdi32.dll",EntryPoint="SelectObject")] public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp); #endregion #region Public Constructor } /// /// This class shall keep the User32 APIs used in our program. /// public class PlatformInvokeUSER32 { #region Class Variables public const int SM_CXSCREEN=0; public const int SM_CYSCREEN=1; #endregion #region Class Functions [DllImport("user32.dll", EntryPoint="GetDesktopWindow")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll",EntryPoint="GetDC")] public static extern IntPtr GetDC(IntPtr ptr); [DllImport("user32.dll",EntryPoint="GetSystemMetrics")] public static extern int GetSystemMetrics(int abc); [DllImport("user32.dll",EntryPoint="GetWindowDC")] public static extern IntPtr GetWindowDC(Int32 ptr); [DllImport("user32.dll",EntryPoint="ReleaseDC")] public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc); #endregion } /// /// This class shall keep all the functionality for capturing /// the desktop. /// public class CaptureScreen { #region Public Class Functions public static Bitmap GetDesktopImage() { //In size variable we shall keep the size of the screen. SIZE size; //Variable to keep the handle to bitmap. IntPtr hBitmap; //Here we get the handle to the desktop device context. IntPtr hDC = PlatformInvokeUSER32.GetDC (PlatformInvokeUSER32.GetDesktopWindow()); //Here we make a compatible device context in memory for screen //device context. IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC); //We pass SM_CXSCREEN constant to GetSystemMetrics to get the //X coordinates of the screen. size.cx = PlatformInvokeUSER32.GetSystemMetrics (PlatformInvokeUSER32.SM_CXSCREEN); //We pass SM_CYSCREEN constant to GetSystemMetrics to get the //Y coordinates of the screen. size.cy = PlatformInvokeUSER32.GetSystemMetrics (PlatformInvokeUSER32.SM_CYSCREEN); //We create a compatible bitmap of the screen size and using //the screen device context. hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap (hDC, size.cx, size.cy); //As hBitmap is IntPtr, we cannot check it against null. //For this purpose, IntPtr.Zero is used. if (hBitmap!=IntPtr.Zero) { //Here we select the compatible bitmap in the memeory device //context and keep the refrence to the old bitmap. IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject (hMemDC, hBitmap); //We copy the Bitmap to the memory device context. PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0,size.cx,size.cy, hDC, 0, 0,PlatformInvokeGDI32.SRCCOPY); //We select the old bitmap back to the memory device context. PlatformInvokeGDI32.SelectObject(hMemDC, hOld); //We delete the memory device context. PlatformInvokeGDI32.DeleteDC(hMemDC); //We release the screen device context. PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32. GetDesktopWindow(), hDC); //Image is created by Image bitmap handle and stored in //local variable. Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap); //Release the memory to avoid memory leaks. PlatformInvokeGDI32.DeleteObject(hBitmap); //This statement runs the garbage collector manually. GC.Collect(); //Return the bitmap return bmp; } //If hBitmap is null, retun null. return null; } #endregion } //This structure shall be used to keep the size of the screen. public struct SIZE { public int cx; public int cy; }

There is also a demo application with this code that shows the use of these classes. It's a very simple Windows application in which there is a simple form with a menu and a picture box control. The Capture Screen menu item of the menu is used to capture the screen and assign to the image property of the picturebox control.

I hope you like this code. I have commented each line of this code to make it self-explanatory. If there is still something confusing to you, please let me know. Good Luck!

Downloads

Download demo project - 12 Kb
Download source - 3 Kb


Comments

  • A little help

    Posted by Bhargav Shah on 01/12/2013 05:16am

    Your code was really useful Agha Ali Raza. (Y) I'm creating a application for my last year project where remote screen capture is my dominating module. With the above code, the image is not re-sized in the picture box. I want the complete image to be shown in the picture box.Currently only the part of the image that fits in the picture box is shown, the rest is cropped. If you could help me with this it would be great :) Thankx :D

    Reply
  • Thank you!

    Posted by minakoga on 04/01/2010 12:16pm

    I want Capture a Window ex: Internet Explorer or any software. Can you help me! Thank you!

    Reply
  • SIMPLE solution in 3 LINES ONLY

    Posted by odyodyodys on 02/24/2010 11:03am

    Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height); Graphics g = Graphics.FromImage(bitmap); g.CopyFromScreen(Point.Empty, Point.Empty, new Size(bitmap.Width, bitmap.Height)); and you are done... g has the image of the primary monitor. If you want screen from another monitor just change the coordinates :)

    Reply
  • using this for desktop sharing

    Posted by spshah99 on 09/12/2006 08:38am

    How can i use this application for sharing my desktop with other remote users?

    Reply
  • what abt linux?

    Posted by ansh on 03/20/2005 12:41pm

    as u used win api for screen capture?what abt linux? another thing is that how i can capture remote screen?

    Reply
  • Screen capture fails for NT service?

    Posted by mkvakin on 08/02/2004 04:12am

    Hi All, The screen capture code provided on this web site works fine for stand-alone applications. But if you try to run it from the service, it will show a black square instead of the screen. Sometimes changing display mode solves the problem. Does anybody know how to fix that? Best regards MK

    Reply
  • Capturing the Screen Image Using C#

    Posted by Legacy on 12/16/2003 12:00am

    Originally posted by: V.srinivasan

    Is there a way we can simulate windows action? Can I enter spcefic values into the screen, simulate mouse actions and read contents of the screen using these dlls?
    please let me know
    thanks
    -Srini

    Reply
  • Get specified window image?

    Posted by Legacy on 03/04/2003 12:00am

    Originally posted by: Charles Laymon

    Could I use this code as a base to get a handle to a specific window (not the desktop but an image of a website that is in a ie window minimized on the desktop) and get an image of it? If so, what do you think the changes might be?

    Reply
  • Help

    Posted by Legacy on 02/28/2003 12:00am

    Originally posted by: Rasha

    Is it possible to send the captured image over a LAN using socket programming?? please we need to know this piece of information urgently...& if the answer is yes could u tell us how ?
    & thank u in advance...:)

    • Yeah Unfortunatley:P lolzz

      Posted by goshi_jinn on 03/24/2005 01:47pm

      Use TcpClient and Tcp Server Classes in the System.Net/System.Net.Socket nbamspaces to comminicate on network 
      serialize this image using binary  formatter get the strem nd the send it on the net work vi TcpClient.Send()........... Need further help or code semple emil me at riz_ahmad@msn.com.
      ll these suggestion given by me keeping in mind that u know C# in general.
      Regards
      Rizwan

      Reply
    Reply
  • is it possible in java

    Posted by Legacy on 02/13/2003 12:00am

    Originally posted by: lokesh gupta

    same video capture of a dekstop in a network make a network manager very much efficent.
    so is it possible to add such type of facility in a network monitor in java if yes how send me your advice

    • possible in java

      Posted by ansh on 03/20/2005 12:50pm

      It is possible in java using the Robot class. It is present in java.awt.Robot namespace

      Reply
    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • According to a recent Forrester total economic impact (TEI) study, enterprises can see a significant reduction in total cost of ownership by accessing Oracle Database in the cloud with a pay-as-you-go subscription model. This subscription service gives businesses the ability to scale up application environments for rapid prototyping, with far less time devoted to procuring licenses and deploying IT infrastructure. Read this study to learn how three different companies use Oracle Database in the cloud and the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds