First you'll need to add references for the following namespaces:
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
Then enumerate your monitors to get the bounding rectangle for all display surfaces and pass that in to the Graphics.CopyFromScreen()
method call:
private static BitmapSource CopyScreen()
{
var left = Screen.AllScreens.Min(screen => screen.Bounds.X);
var top = Screen.AllScreens.Min(screen => screen.Bounds.Y);
var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width);
var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height);
var width = right - left;
var height = bottom - top;
using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
{
using (var bmpGraphics = Graphics.FromImage(screenBmp))
{
bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height));
return Imaging.CreateBitmapSourceFromHBitmap(
screenBmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
}
}
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…