Looking to modify the following to take a screenshot off all monitors. I have tried adapting it but my images are blank. Writing it to test.png is for testing. The byte[]
will be sent to the receiving app.
public byte[] Take()
{
int screenWidth = Convert.ToInt32(SystemParameters.VirtualScreenWidth);
int screenHeight = Convert.ToInt32(SystemParameters.VirtualScreenHeight);
int screenLeft = Convert.ToInt32(SystemParameters.VirtualScreenLeft);
int screenTop = Convert.ToInt32(SystemParameters.VirtualScreenTop);
RenderTargetBitmap renderTarget = new RenderTargetBitmap(screenWidth, screenHeight, 96, 96, PixelFormats.Pbgra32);
VisualBrush sourceBrush = new VisualBrush();
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
using (drawingContext)
{
drawingContext.PushTransform(new ScaleTransform(1, 1));
drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(screenWidth, screenHeight)));
}
renderTarget.Render(drawingVisual);
PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
Byte[] _imageArray;
using (MemoryStream outputStream = new MemoryStream())
{
pngEncoder.Save(outputStream);
_imageArray = outputStream.ToArray();
}
using (FileStream stream = new FileStream(@"c:\test.png", FileMode.Create, FileAccess.ReadWrite))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(_imageArray);
}
}
return _imageArray;
}
First you'll need to add references for the following namespaces:
Then enumerate your monitors to get the bounding rectangle for all display surfaces and pass that in to the
Graphics.CopyFromScreen()
method call:Bear in mind though that monitors often don't fit neatly into a single rectangle, particularly if they have different resolution etc, so you might be better snap-shotting the individual screens. Either way, the solution to your problem is to change the coordinates that you were passing in to the
Graphics.CopyFromScreen()
method call.EDIT: see Demetris Leptos's comment below, the code I've posted in this answer should be calling DeleteObject on the bitmap returned by
screenBmp.GetHbitmap()
so as to avoid a memory leak, as specified in the MSDN documentation.