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# 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...

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV...