I am trying to get a screenshot of the whole virtual screen. This means, an image of not just the primary screen, but every screen connected to the computer.
Is there a way to do that? I tried using this, but it didn't work:
Bitmap b = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
Graphics g = Graphics.FromImage(b);
this.Size = new Size(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
g.CopyFromScreen(0, 0, 0, 0, b.Size);
The documentation says: Graphics.CopyFromScreen(Int32, Int32, Int32, Int32, Size)
: Performs a bit-block transfer of the color data, corresponding to a rectangle of pixels, from the screen to the drawing surface of the Graphics." But the virtual screen is not necessarily a rectangle: imagine two monitors with 1920x1200 and 1280x1024 resolutions. So what you need to do is create a bitmap like you do, then enumerate your monitors and execute CopyFromScreen()
for each of them.
Edit: If, for instance, you have two monitors, the one having 1280x1024 resolution standing on the left of 1920x1200 one, then the coordinates of the former would be (-1280,0) - (0, 1024). Therefore you need to execute memoryGraphics.CopyFromScreen(-1280, 0, 0, 0, s);
where s is the Size(1280,1024)
. For the second one you need to call memoryGraphics.CopyFromScreen(0, 0, *1280*, 0, s);
and s would be the Size(1920, 1200)
.
Hope this helps.
Like Igor and Hans have said, you have to indicate the source coordinate :
Bitmap screenshot = new Bitmap(
SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height,
PixelFormat.Format32bppArgb);
Graphics screenGraph = Graphics.FromImage(screenshot);
screenGraph.CopyFromScreen(
SystemInformation.VirtualScreen.X,
SystemInformation.VirtualScreen.Y,
0,
0,
SystemInformation.VirtualScreen.Size,
CopyPixelOperation.SourceCopy);
Igor is right, passing 0, 0 for the SourceX/Y arguments isn't correct. Iterate the Screen instances in the Screen.AllScreens
property to find the bounding rectangle. Beware that CopyFromScreen()
has a bug, it cannot capture layered windows (the kind that has TransparencyKey
or Opacity
set). Check my answer in this thread for a workaround.
Beware that capturing the entire desktop isn't always practical, you'll get lots of black when the screens are not arranged in a perfect rectangle and an OutOfMemory
exception is not uncommon on a 32-bit machine with high resolution displays.