I have tried using GDI+ and SlimDX to capture the screen.
Surprisingly, the good old GDI+ was faster for me, for unknown reasons (averaging 38-50ms for a screenshot).
SlimDX is slower, averaging 40-80ms (it spikes really often) and also, _device.GetFrontBufferData(0, _surface);
makes a memory leak that I don't know how to fix.
What can I use to take fast screenshots in real time ? If this makes any difference, the purpose of this will be to save it in a .avi later on, or possibly stream that sequence of images in real time.
Below I show the code I am using for both GDI+ (commented out) and SlimDX. You will need a reference to SlimDX.dll for this to work
using SlimDX;
using SlimDX.Direct3D9;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
namespace DxCapture
{
public partial class Form1 : Form
{
static Device _device;
static AdapterInformation _adapterInfo;
static Surface _surface;
static Bitmap _bitmap = new Bitmap(1920, 1080);
public Form1()
{
InitializeComponent();
timer1.Start();
DoubleBuffered = true;
Direct3D _direct3D9 = new Direct3D();
_adapterInfo = _direct3D9.Adapters.DefaultAdapter;
PresentParameters present_params = new PresentParameters();
present_params.Windowed = true;
present_params.SwapEffect = SwapEffect.Discard;
_device = new Device(new Direct3D(), 0, DeviceType.Hardware,
(IntPtr)0, CreateFlags.SoftwareVertexProcessing,
present_params);
_surface = Surface.CreateOffscreenPlain(_device,
_adapterInfo.CurrentDisplayMode.Width,
_adapterInfo.CurrentDisplayMode.Height,
Format.A8R8G8B8, Pool.SystemMemory);
}
private void timer1_Tick(object sender, EventArgs e)
{
Stopwatch _watch = Stopwatch.StartNew();
// -------- Method 1: SlimDX --------
_device.GetFrontBufferData(0, _surface);
_bitmap.Dispose();
_bitmap = new Bitmap(Surface.ToStream(_surface,
ImageFileFormat.Bmp, new Rectangle(0, 0, 1920, 1080)));
this.BackgroundImage = (Image)_bitmap;
// -------- Method 2: GDI+ --------
//_bitmap.Dispose();
//_bitmap = new Bitmap(1920, 1080);
//using (Graphics g = Graphics.FromImage(_bitmap))
// g.CopyFromScreen(0, 0, 0, 0, new Size(1920, 1080));
//this.BackgroundImage = (Image)_bitmap;
_watch.Stop();
Console.WriteLine(_watch.Elapsed.TotalMilliseconds);
}
}
}