Skip to main content

C# - Taking Some Screenshots with C# [Beginner]


We do some pretty neat things with all sorts of code, and all this requires a ton of screenshots to help explain all the craziness. But besides having that good ol' fashion "Print Screen" button, we can actually use C# to take a screenshot for us. The best part of all is that it is only a couple lines of code. So lets just go ahead and dive right into it.

Now, all we are going to do is create a function that you can call whenever you need to take a screenshot. The first thing we need to do is add a using statement, because we are going to use a non-standard namespace. We need to include the System.Drawing.Imaging namespace in order for this to work:
Using System.Drawing.Imaging;
 
That will let us use the basic yet powerful methods that will help take a screenshot. The first thing we need to do is setup an empty method to fill up. To start, our method will take in nothing and return a bitmap, so it will look something like this:
public Bitmap ScreenShot()
{

}
 
Simple enough, right? Even better, technically to get a basic screenshot we need only 3 lines of code in this function. The first line will be a declaration for a new bitmap object:
Bitmap screenShotBMP = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
    Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);

All we are doing is making a standard C# Bitmap object that is the size of the primary display on the computer. The Screen class has some pretty neat stuff, but that is for later, now we must create a Graphics object:
Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);
 
Put simply, this object helps set up a canvas, but a graphics object also helps with the drawing as well. Oddly enough, this class has a method called CopyFromScreen. Yep, you guessed it, this is the method that copies a portion of the screen for us. We will be using the screen object again to get the size of the screen. For the first screenshot we will just get the whole thing:
screenShotGraphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
    Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size,
    CopyPixelOperation.SourceCopy);
 
All this line does is copy a portion of the screen, the whole screen in this case, in a specific format. With those 3 lines of code, we have a Bitmap object filled with a nice screen-size screenshot. All that is left for this method is to return the bitmap object. The final version will look like so:
public Bitmap ScreenShot()
{
    Bitmap screenShotBMP = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
        Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);

    Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);

    screenShotGraphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
        Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size,
        CopyPixelOperation.SourceCopy);

    screenShotGraphics.Dispose();

    return screenShotBMP;
}
 
A simple primary screen
Screenshot

Wait, wait a second. This method does some justice if you have one screen, but what kind of developer has only one screen? Well, thankfully the screen class has this handy Screen array that holds the information for all the screens on the system. The only issue is that we have to loop through all the Screens to get the information we need. The good flip side is that this fix will handle 2, 3, or however many screens wide.

As with any addition to a program, we have to add some new variables. Actually we only need one new variable that will go at the top of our ScreenShot method:
Rectangle totalSize = Rectangle.Empty;
 
This one variable will hold all the screen size data for all of the screens on the current computer. These screens can be any different size in any order, it doesn't matter, the method will catch it.

So now that we have our nice empty rectangle, we can go ahead and fill it with the needed screen size information. First we must loop through the Screens in the screens array. For each screen, we need to take the Bounds member and take its information (in rectangle form) and then add it to totalSize. The whole loop is actually just one line, so we can use the one-liner no-bracket shortcut:
foreach (Screen s in Screen.AllScreens)
  totalSize = Rectangle.Union(totalSize, s.Bounds);
 
All we are doing here is using a little static method called Rectangle.Union, which adds two rectangles together and returns the new rectangle. So for each screen, we just add the Bounds rectangle to the current totalSize object. When the loop is finished, we have a pretty filled rectangle, the size of all the screens combined.

The last step in this process is to change around our original code. We need to change 3 things: The width and height of our bitmap, and the size passed to the CopyFromScreen call. So, after those changes, the final method is:
public Bitmap ScreenShot()
{
  Rectangle totalSize = Rectangle.Empty;

  foreach (Screen s in Screen.AllScreens)
    totalSize = Rectangle.Union(totalSize, s.Bounds);

  Bitmap screenShotBMP = new Bitmap(totalSize.Width, totalSize.Height,
      PixelFormat.Format32bppArgb);

  Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);

  screenShotGraphics.CopyFromScreen(totalSize.X, totalSize.Y,
      0, 0, totalSize.Size, CopyPixelOperation.SourceCopy);

  screenShotGraphics.Dispose();

  return screenShotBMP;
}
 
All we are doing in our final changes is using our totalSize rectangle object to set the size of the bitmap and graphics object, as opposed to using Screen.PrimaryScreen. The sets all the objects we use to the right size to accommodate all the screens on the computer. With this method, you can get a screenshot from almost any computer setup. The final result will look something like:

A Full
Screenshot

Now this will return a Bitmap object, which can be used any number of ways. The Bitmap class actually has a Save method that takes in a path and image format, so you can actually save the image with one line of code. You can also use a picture box and view a shrunk down version of your screenshot. Anything that you can do with a Bitmap object, you can do with your screenshot. You can also tweak the numbers passed into the CopyFromScreen method if you only want a portion of the screen.

And with that, this tutorial wraps up. A Full Visual Studio Solution can be found here.

Source Files:

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >();

C# Snippet - The Many Uses Of The Using Keyword [Beginner]

What is the first thing that pops into your mind when you think of the using keyword for C#? Probably those lines that always appear at the top of C# code files - the lines that import types from other namespaces into your code. But while that is the most common use of the using keyword, it is not the only one. Today we are going to take a look at the different uses of the using keyword and what they are useful for. The Using Directive There are two main categories of use for the using keyword - as a "Using Directive" and as a "Using Statement". The lines at the top of a C# file are directives, but that is not the only place they can go. They can also go inside of a namespace block, but they have to be before any other elements declared in the namespace (i.e., you can't add a using statement after a class declaration). Namespace Importing This is by far the most common use of the keyword - it is rare that you see a C# file that does not h

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as