How to Take Screenshots Programmatically in C#
Have you ever needed to take screenshots of your computer screen automatically from a C# program? Maybe you‘re building a tool to document user steps, creating automated tests that verify the UI, or making a screen capture utility. Whatever the reason, C# provides a few different ways to take screenshots programmatically. In this guide, we‘ll look at how to capture the screen, windows, and regions as images in a variety of formats. We‘ll walk through complete code examples for different approaches so you can easily add this useful functionality to your C# applications.
Why Take Screenshots Programmatically?
Before we dive into the code, let‘s consider a few scenarios where you might want your C# program to take screenshots:
- Creating a step-by-step software usage guide
- Visually documenting a process or issue
- Automated UI testing and verification
- Monitoring of remote, unattended systems
- Capturing images/frames from a video stream
- Implementing screen capture and sharing tools
- Saving snapshots of a visualization or game state
The uses for programmatically generated screenshots are endless. And fortunately, C# makes it fairly straightforward to do. There are a few main approaches we‘ll look at.
Approaches to Taking Screenshots in C
There are three primary ways to take screenshots from a C# application:
- Using Windows API calls like BitBlt
- Using the .NET Graphics class
- Using third-party libraries
The first two options use native .NET functionality, while the third relies on open source or commercial libraries to simplify the process. We‘ll look at examples of each, but first let‘s clarify a few key concepts.
Key Concepts
Before looking at the code, there are a few key things to understand:
- The screen consists of a grid of pixels, each with a color
- A screenshot is just an image file (like a PNG or JPG) containing the colors of each pixel
- The image resolution will match the resolution of the screen area captured
- The cursor is not automatically included in screenshots and must be drawn separately
- You can capture the entire screen, a window, or any rectangular portion of the screen
With that foundation, let‘s look at our first approach to capturing screenshots in C#.
Approach 1: Windows API (BitBlt)
Windows provides an API function called BitBlt (bit-block transfer) for copying graphic data from one device to another. This can be used to copy the screen contents to an image. Here‘s a complete code example:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
class Program
{
[DllImport("user32.dll")]
static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
static void Main(string[] args)
{
int screenWidth = Screen.PrimaryScreen.Bounds.Width;
int screenHeight = Screen.PrimaryScreen.Bounds.Height;
using (Bitmap bmp = new Bitmap(screenWidth, screenHeight))
{
using (Graphics g = Graphics.FromImage(bmp))
{
IntPtr hdc = g.GetHdc();
BitBlt(hdc, 0, 0, screenWidth, screenHeight, hdc, 0, 0, (int)CopyPixelOperation.SourceCopy);
if (GetCursorPos(out POINT p))
{
Cursors.Default.Draw(g, new Rectangle(p.X, p.Y, 32, 32));
}
g.ReleaseHdc(hdc);
}
bmp.Save(@"C:\screenshot.png", ImageFormat.Png);
}
}
}
This code uses the BitBlt function to copy the screen contents into a bitmap, then saves that bitmap as a PNG image file. It also demonstrates capturing the position of the mouse cursor and drawing it on the screenshot.
The key steps are:
- Get the screen dimensions
- Create a bitmap to hold the screenshot
- Get a Graphics object from the bitmap
- Use BitBlt to copy the screen into the bitmap
- Optionally draw the mouse cursor icon
- Save the bitmap to a file
By changing the dimensions and position used in the BitBlt call, you can capture a specific window or region of the screen instead of the full screen.
While this approach works, it requires using Windows API calls and structures, which can be a bit arcane. Let‘s look at a second approach using the .NET Graphics class.
Approach 2: .NET Graphics Class
The .NET framework provides a Graphics class that can be used to capture windows or the screen to an image. Here‘s an example of using it to capture the entire screen to a file:
using System;
using System.Drawing;
using System.Drawing.Imaging;
class Program
{
static void Main()
{
Rectangle bounds = Screen.GetBounds(Point.Empty);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
bitmap.Save("screenshot.jpg", ImageFormat.Jpeg);
}
}
}
This code is more concise than the Windows API version. The key steps are:
- Get the screen bounds
- Create a bitmap to hold the screenshot
- Get a Graphics object from the bitmap
- Use Graphics.CopyFromScreen to copy the screen into the bitmap
- Save the bitmap to a file
You can modify this to capture a specific window by getting the window‘s bounds and using those dimensions instead of the full screen.
To capture a region of the screen, you can use the Graphics.CopyFromScreen overload that takes a source and destination rectangle:
Rectangle region = new Rectangle(100, 100, 500, 400);
g.CopyFromScreen(region.Location, Point.Empty, region.Size);
This will capture a 500×400 pixel region starting at coordinates 100,100.
The Graphics approach is more straightforward than the Windows API, but still requires a bit of code. For the simplest solution, we can turn to third-party libraries.
Approach 3: Third-Party Libraries
There are a number of open source and commercial libraries available that make capturing screenshots from C# a breeze. Let‘s look at two popular options: Gemini and ScreenCapture.NET.
Gemini
Gemini is a paid .NET library that provides a variety of screen capture functions. With Gemini, you can capture the screen, a window, or a region in a single line of code. For example, to capture the full screen:
using Gemini;
using Gemini.Capture;
...
Snippets.Save(@"C:\screenshot.png", Snippets.Capture(Snippets.Screen()));
Gemini uses a fluent, chainable syntax where you select what to capture and what to do with the captured image. It supports saving in a variety of image formats.
To capture a specific window given its title:
Snippets.Save(@"C:\screenshot.png", Snippets.Capture(Snippets.Window("Untitled - Notepad")));
Or to capture a region of the screen:
Snippets.Save(@"C:\screenshot.png", Snippets.Capture(Snippets.Region(100, 100, 400, 500)));
Gemini makes common screen capture tasks trivially easy. Of course, it does come at the cost of a license fee for commercial use. For a free, open source alternative, check out ScreenCapture.NET
ScreenCapture.NET
ScreenCapture.NET is a free, open source library for capturing screenshots in .NET applications. With ScreenCapture.NET, you can capture the full screen, a window, or a region in just a couple lines of code.
Here‘s how to use it to capture the full screen to a file:
using ScreenCapture;
using System.Drawing;
...
Screenshot screenshot = new Screenshot()
Image img = screenshot.CaptureScreen();
img.Save("screenshot.png", ImageFormat.Png);
To capture a specific window, you first need to get a handle to the window, then pass that to the CaptureWindow method:
IntPtr handle = Process.GetProcessesByName("notepad")[0].MainWindowHandle;
Image img = screenshot.CaptureWindow(handle);
And to capture a screen region:
Rectangle region = new Rectangle(100, 100, 500, 400);
Image img = screenshot.CaptureRegion(region);
ScreenCapture.NET makes it very simple to take all kinds of screenshots from C# apps, and you have the full source code to customize it however you like.
Summary
We‘ve looked at three different approaches for capturing screenshots programmatically in C#:
- Using the Windows API BitBlt function
- Using the .NET Graphics class
- Using third-party libraries like Gemini and ScreenCapture.NET
Which approach you choose depends on your requirements and constraints. The Windows API gives you the most control but is harder to use. The Graphics class is a bit simpler but still requires a handful of lines of code. Third-party libraries make it dead simple but may cost money or add dependencies to your project.
Whichever way you go, C# makes it possible to capture the full screen, application windows, or screen regions and save them to image files. With these techniques, you can build all sorts of utilities and automation tools that rely on grabbing pixels from the screen.
Further Reading
To learn more about taking screenshots programmatically in C#, check out these helpful resources:
Hopefully this guide has helped you understand how to take control of screenshots in your C# applications. Armed with this knowledge, you can build some really cool utilities and tools. Happy coding!