I have create the helper class to capture the selected area on specific screen where control reside. It works on multiple screens.
The idea is taken from multiple online resources that basically Freeze the Screen and put into PictureBox .NET control.
Here's the codes:
public class CaptureScreen : IDisposable
{
readonly Control control;
readonly Pen penSelectedAreaScreenShot;
Form frmPictureBox = null;
PictureBox pictureBoxScreenShot = null;
Point selectedScreenShotStartPoint;
Size selectedScreenShotSize;
bool isMouseDownSelectedScreenShot = false;
public event Action SelectedScreenAreaCaptured;
public event Action ScreenCaptureFailed;
public CaptureScreen(Control control)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
this.control = control;
this.penSelectedAreaScreenShot = new Pen(Color.Red, 1);
this.penSelectedAreaScreenShot.DashStyle = DashStyle.Dot;
}
public void BeginStart()
{
#region Setup the Picture Box for ScreenShot
if (this.frmPictureBox != null)
{
this.frmPictureBox.Close();
this.frmPictureBox.Dispose();
this.frmPictureBox = null;
}
if (this.pictureBoxScreenShot != null)
{
this.pictureBoxScreenShot.Dispose();
this.pictureBoxScreenShot = null;
}
this.frmPictureBox = new Form
{
BackColor = Color.Black,
Cursor = Cursors.Cross,
FormBorderStyle = FormBorderStyle.None,
StartPosition = FormStartPosition.CenterParent,
TopLevel = true,
TopMost = true,
Top = 0,
Left = 0,
WindowState = FormWindowState.Maximized,
KeyPreview = true
};
this.pictureBoxScreenShot = new PictureBox
{
Location = new Point(0, 0),
SizeMode = PictureBoxSizeMode.Zoom
};
this.frmPictureBox.Controls.Add(this.pictureBoxScreenShot);
#endregion
#region Capture the Screen
Bitmap screenShotBitmap = null;
Graphics graphics = null;
MemoryStream stream = null;
try
{
Screen currentScreen = Screen.FromControl(this.control);
screenShotBitmap = new Bitmap(currentScreen.Bounds.Width, currentScreen.Bounds.Height);
graphics = Graphics.FromImage(screenShotBitmap as Image);
graphics.CopyFromScreen(currentScreen.Bounds.X, currentScreen.Bounds.Y, 0, 0, screenShotBitmap.Size);
stream = new MemoryStream();
screenShotBitmap.Save(stream, ImageFormat.Png);
this.pictureBoxScreenShot.Size = screenShotBitmap.Size;
this.pictureBoxScreenShot.Image = Image.FromStream(stream);
}
catch (Exception ex)
{
if (this.ScreenCaptureFailed != null)
{
this.ScreenCaptureFailed(this, ex);
}
}
finally
{
if (stream != null)
{
stream.Close();
stream.Dispose();
stream = null;
}
if (graphics != null)
{
graphics.Dispose();
graphics = null;
}
if (screenShotBitmap != null)
{
screenShotBitmap.Dispose();
screenShotBitmap = null;
}
}
#endregion
this.frmPictureBox.KeyDown += this.frmPictureBox_KeyDown;
this.pictureBoxScreenShot.MouseMove += this.pictureBoxScreenShot_MouseMove;
this.pictureBoxScreenShot.MouseDown += this.pictureBoxScreenShot_MouseDown;
this.pictureBoxScreenShot.MouseUp += this.pictureBoxScreenShot_MouseUp;
this.frmPictureBox.Show(this.control);
}
public void Exit()
{
if (this.frmPictureBox != null)
{
this.frmPictureBox.Close();
this.frmPictureBox.Dispose();
this.frmPictureBox = null;
}
if (this.pictureBoxScreenShot != null)
{
this.pictureBoxScreenShot.Dispose();
this.pictureBoxScreenShot = null;
}
this.isMouseDownSelectedScreenShot = false;
}
[DebuggerStepThrough]
void frmPictureBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
this.Exit();
}
}
void pictureBoxScreenShot_MouseMove(object sender, MouseEventArgs e)
{
if (this.pictureBoxScreenShot.Image == null)
{
this.Exit();
return;
}
if (this.isMouseDownSelectedScreenShot)
{
this.pictureBoxScreenShot.Refresh();
this.selectedScreenShotSize = new Size(
e.X - this.selectedScreenShotStartPoint.X,
e.Y - this.selectedScreenShotStartPoint.Y);
// Draw the selected area rectangle.
this.pictureBoxScreenShot.CreateGraphics().DrawRectangle(this.penSelectedAreaScreenShot,
this.selectedScreenShotStartPoint.X, this.selectedScreenShotStartPoint.Y,
this.selectedScreenShotSize.Width, this.selectedScreenShotSize.Height);
}
}
void pictureBoxScreenShot_MouseDown(object sender, MouseEventArgs e)
{
if (!this.isMouseDownSelectedScreenShot)
{
if (e.Button == MouseButtons.Left)
{
this.selectedScreenShotStartPoint = new Point(e.X, e.Y);
}
this.pictureBoxScreenShot.Refresh();
this.isMouseDownSelectedScreenShot = true;
}
}
void pictureBoxScreenShot_MouseUp(object sender, MouseEventArgs e)
{
if (this.pictureBoxScreenShot.Image == null)
{
this.Exit();
return;
}
isMouseDownSelectedScreenShot = false;
this.frmPictureBox.Hide();
// Check whether there is something get selected.
if (this.selectedScreenShotSize.Width > 0 && this.selectedScreenShotSize.Height > 0)
{
Bitmap selectedAreaBitmap = null;
Graphics graphics = null;
Bitmap screenShotBitmap = null;
try
{
selectedAreaBitmap = new Bitmap(this.selectedScreenShotSize.Width, this.selectedScreenShotSize.Height);
graphics = Graphics.FromImage(selectedAreaBitmap);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
screenShotBitmap = new Bitmap(this.pictureBoxScreenShot.Image, this.pictureBoxScreenShot.Size);
graphics.DrawImage(screenShotBitmap, 0, 0, new Rectangle(this.selectedScreenShotStartPoint, this.selectedScreenShotSize), GraphicsUnit.Pixel);
if (this.SelectedScreenAreaCaptured != null)
{
this.SelectedScreenAreaCaptured(this, selectedAreaBitmap);
}
else
{
Clipboard.SetImage(selectedAreaBitmap);
MessageBox.Show(this.control, "Selected Screen is copied to Clipboard.");
}
}
catch (Exception ex)
{
if (this.ScreenCaptureFailed != null)
{
this.ScreenCaptureFailed(this, ex);
}
}
finally
{
if (screenShotBitmap != null)
{
screenShotBitmap.Dispose();
screenShotBitmap = null;
}
if (graphics != null)
{
graphics.Dispose();
graphics = null;
}
if (selectedAreaBitmap != null)
{
selectedAreaBitmap.Dispose();
selectedAreaBitmap = null;
}
}
}
this.Exit();
}
#region IDisposable Member
public void Dispose()
{
try
{
this.Exit();
}
catch { }
}
#endregion
}
And you can use it like this:
CaptureScreen captureScreen = new CaptureScreen(this);
// If event not implement, then by default it will copied to clipboard.
//captureScreen.SelectedScreenAreaCaptured += delegate(object am_sender, Bitmap am_selectedAreaBitmap)
//{
//string destFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), String.Format("Capture_{0}.png", DateTime.Now.ToString("yyyyMMddHHmmss")));
//am_selectedAreaBitmap.Save(destFilename, System.Drawing.Imaging.ImageFormat.Png);
//};
// Implements this to handle the exception that occurs during screen capture.
//captureScreen.ScreenCaptureFailed += delegate(object am_sender, Exception am_ex)
//{
//MessageBox.Show(this, am_ex.Message, "Unable to Capture the Screen", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
//};
captureScreen.BeginStart();