Introduction
There are a lot of articles about screen capturing, but most of them use Win32 API functions, even in .NET 2.0, where this is not necessary because .NET 2.0 has all classes needed to implement that.
Background
It's often necessary to get a screenshot of the entire screen or parts of it. In our applications, we often use systems with multiple monitors, requiring us to capture all of them at once or each screen separately. Just remember, the virtual screen is the complete view of all monitors attached to the system, the primary screen is the view of the main monitor, and the working screen is the same but excluding the task bar.
Using the code
The class 'ScreenCapture
' supplies a couple of methods allowing to capture the complete virtual screen, the primary screen, the working screen, a specific form (complete or only the client area), and only the contents of a specific control in a form. The images captured may be used directly from your code, or they can be saved into a file or printed. There is another small helper class 'ImageFormatHandler
' which is used to handle the different graphic file formats when saving the captured image.
The source
The source code files include the two classes described, and may be directly used in your code. It's built with Visual Studio 2005.
Our main capturing method looks like below:
public Bitmap[] Capture( CaptureType typeOfCapture )
{
Bitmap memoryImage;
int count = 1;
try
{
Screen[] screens = Screen.AllScreens;
Rectangle rc;
switch ( typeOfCapture )
{
case CaptureType.PrimaryScreen:
rc = Screen.PrimaryScreen.Bounds;
break;
case CaptureType.VirtualScreen:
rc = SystemInformation.VirtualScreen;
break;
case CaptureType.WorkingArea:
rc = Screen.PrimaryScreen.WorkingArea;
break;
case CaptureType.AllScreens:
count = screens.Length;
typeOfCapture = CaptureType.WorkingArea;
rc = screens[0].WorkingArea;
break;
default:
rc = SystemInformation.VirtualScreen;
break;
}
images = new Bitmap[count];
for ( int index = 0; index < count; index++ )
{
if ( index > 0 )
rc = screens[index].WorkingArea;
memoryImage = new Bitmap( rc.Width, rc.Height,
PixelFormat.Format32bppArgb );
using ( Graphics memoryGrahics =
Graphics.FromImage( memoryImage ) )
{
memoryGrahics.CopyFromScreen( rc.X, rc.Y,
0, 0, rc.Size, CopyPixelOperation.SourceCopy );
}
images[index] = memoryImage;
}
}
catch ( Exception ex )
{
MessageBox.Show( ex.ToString(), "Capture failed",
MessageBoxButtons.OK, MessageBoxIcon.Error );
}
return images;
}
The variable images
used is a member of this class, and is of type Bitmap[]
. The parameter typeOfCapture
of this method is an enum
type defined in this class, and is used to select what actually should be captured.
There is another capture method which is used to selectively capture the contents of controls, forms, or their client area. It works quite similar to the one shown above.
private Bitmap capture( Control window, Rectangle rc )
{
Bitmap memoryImage = null;
images = new Bitmap[1];
using ( Graphics graphics = window.CreateGraphics() )
{
memoryImage = new Bitmap( rc.Width,
rc.Height, graphics );
using ( Graphics memoryGrahics =
Graphics.FromImage( memoryImage ) )
{
memoryGrahics.CopyFromScreen( rc.X, rc.Y,
0, 0, rc.Size, CopyPixelOperation.SourceCopy );
}
}
images[0] = memoryImage;
return memoryImage;
}
Several other methods are used to do all the work needed for saving/printing the captured image, they are all described in comments in the source code.
public void Save( String filename,
ImageFormatHandler.ImageFormatTypes format )
The parameter filename
holds the desired name with a complete path, the extension will be substituted depending on the file type selected by the parameter format
.
This methods loads some parameters depending on the file format chosen:
ImageCodecInfo info;
EncoderParameters parameters =
formatHandler.GetEncoderParameters( format, out info );
That's where we use the helper class ImageFormatHandler
which does all that. I think this is a base which can be used for customizing to your own needs.
Changes
The actual example has been updated by some method, which can be used to capture screens from other processes; to do that, native code must be used. Then it is no longer a pure .NET 2.0 solution. We also did not test this solution with layered forms, but a bit of modification in the base capturing method should enable this.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.