Take Screenshot of Multiple Desktops of All Visible Applications and Forms

C#/.Net code to screen capture multiple monitors with scaling

We needed a solution so I did some experimenting. First of all, we needed a C# class for some Windows methods. This code is stolen, not original.

class NativeUtilities
{
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>This is the primary display.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x16,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DisplayDevice
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}

[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public ScreenOrientation dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}

[DllImport("user32.dll")]
public static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);

public const int ENUM_CURRENT_SETTINGS = -1;
const int ENUM_REGISTRY_SETTINGS = -2;

[DllImport("User32.dll")]
public static extern int EnumDisplayDevices(string lpDevice, int iDevNum, ref DisplayDevice lpDisplayDevice, int dwFlags);
}

Then I wrote a method to call this code, using the above Windows methods, as opposed to the .Net methods we had been using:

    public static void ScreenCapture(string filename)
{
// Initialize the virtual screen to dummy values
int screenLeft = int.MaxValue;
int screenTop = int.MaxValue;
int screenRight = int.MinValue;
int screenBottom = int.MinValue;

// Enumerate system display devices
int deviceIndex = 0;
while (true)
{
NativeUtilities.DisplayDevice deviceData = new NativeUtilities.DisplayDevice{cb = Marshal.SizeOf(typeof(NativeUtilities.DisplayDevice))};
if (NativeUtilities.EnumDisplayDevices(null, deviceIndex, ref deviceData, 0) != 0)
{
// Get the position and size of this particular display device
NativeUtilities.DEVMODE devMode = new NativeUtilities.DEVMODE();
if (NativeUtilities.EnumDisplaySettings(deviceData.DeviceName, NativeUtilities.ENUM_CURRENT_SETTINGS, ref devMode))
{
// Update the virtual screen dimensions
screenLeft = Math.Min(screenLeft, devMode.dmPositionX);
screenTop = Math.Min(screenTop, devMode.dmPositionY);
screenRight = Math.Max(screenRight, devMode.dmPositionX + devMode.dmPelsWidth);
screenBottom = Math.Max(screenBottom, devMode.dmPositionY + devMode.dmPelsHeight);
}
deviceIndex++;
}
else
break;
}

// Create a bitmap of the appropriate size to receive the screen-shot.
using (Bitmap bmp = new Bitmap(screenRight - screenLeft, screenBottom - screenTop))
{
// Draw the screen-shot into our bitmap.
using (Graphics g = Graphics.FromImage(bmp))
g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size);

// Stuff the bitmap into a file
bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
}
}

This works and has been pulled from a large application. I hope I've included all the necessary pieces.

Capture the Screen into a Bitmap

You can use the Graphics.CopyFromScreen() method.

//Create a new bitmap.
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);

// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);

// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);

// Save the screenshot to the specified path that the user has chosen.
bmpScreenshot.Save("Screenshot.png", ImageFormat.Png);

Capture screenshot of active window?

ScreenCapture sc = new ScreenCapture();
// capture entire screen, and save it to a file
Image img = sc.CaptureScreen();
// display image in a Picture control named imageDisplay
this.imageDisplay.Image = img;
// capture this window, and save it
sc.CaptureWindowToFile(this.Handle,"C:\\temp2.gif",ImageFormat.Gif);

http://www.developerfusion.com/code/4630/capture-a-screen-shot/

Screen Overlay For Screenshot

Sure, just create a borderless, translucent window that covers all of the desktop screens.

You can find the right Rectangle to cover all of the screens with the following LINQ:

Rectangle bounds = Screen.AllScreens
.Select(x => x.Bounds)
.Aggregate(Rectangle.Union);

Then set the Left, Top, Width and Height of the Window from bounds



Related Topics



Leave a reply



Submit