For a very long time ago, in one of my projects, I needed to capture the screenshot which must have to support both full screen capturing and specific regional capturing.
Also I need to paste that captured image back to the screen programmatically. At that moment I solved my problem by using some WinApi methods in the user32.dll and gdi32.dll. Here I want to share that code with you.
To use this code;
Use CaptureScreen() method to capture whole screen;
Use CatureRegion(Region) to capture only the given region of the screen;
Use PasteToScreen(Bitmap, Region) method to paste any image to the given region on to the screen.
public class NativeMethods
{
//
// Takes a screenshot of full screen
//Return the Bitmap of the Screen
public static Bitmap CaptureScreen()
{
return CaptureRegion(null);
}
// Takes a Screen Shot of the given rectangle.
//Rectangle area which we try to get the screen shot.
// Return the Bitmap of the screen defined rectangle.
public static Bitmap CaptureRegion(Rectangle rct)
{
return CaptureRegion(new Region(rct));
}
/// Takes a screen shot of the given region.
///Region that which we try to get the picture of it.
/// Returns the Bitmap of the given region.
/// Bitmap Size will be equal to the GetBounds() of the Region.
/// Any other points that they are not in the region and
/// which are in the Bounds will be as Color.Transparent.
public static Bitmap CaptureRegion(Region rgn)
{
IntPtr hSDc, hMDc; IntPtr hBtm, hOldBtm;
Size imgSize = Size.Empty;
int xCoor = 0, yCoor = 0;
if (rgn == null)
{
hSDc = CreateDC("DISPLAY", string.Empty,string.Empty, string.Empty);
hMDc = CreateCompatibleDC(hSDc);
imgSize = new Size(GetDeviceCaps(hSDc, 8), GetDeviceCaps(hSDc, 10));
GraphicsPath p = new GraphicsPath();
p.AddRectangle(new Rectangle(0, 0, imgSize.Width, imgSize.Height));
rgn = new Region(p);
} else
{
hSDc = GetDC(IntPtr.Zero);
SelectClipRgn(hSDc, rgn.GetHrgn(Graphics.FromHdc(hSDc)));
hMDc = CreateCompatibleDC(hSDc);
RECT myBox = new RECT();
GetClipBox(hSDc, ref myBox);
imgSize = new Size(myBox.Width, myBox.Height);
xCoor = myBox.left; yCoor = myBox.top;
}
hBtm = CreateCompatibleBitmap(hSDc, imgSize.Width, imgSize.Height);
hOldBtm = SelectObject(hMDc, hBtm);
BitBlt(hMDc, 0, 0, imgSize.Width, imgSize.Height, hSDc, xCoor, yCoor, RasterOperations.SRCCOPY);
hBtm = SelectObject(hMDc, hOldBtm);
DeleteDC(hSDc); DeleteDC(hMDc);
Bitmap bmp = Bitmap.FromHbitmap(hBtm);
RectangleF rct = rgn.GetBounds(Graphics.FromImage(bmp));
RectangleF[] rcts = rgn.GetRegionScans(new Matrix());
for (int i = 0; i < rcts.Length; i++)
{
rcts[i].X -= rct.X;
rcts[i].Y -= rct.Y;
}
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
bool isIn = IsInRectangles(rcts, (float)x, (float)y);
if (!isIn)
bmp.SetPixel(x, y, Color.Transparent);
}
}
DeleteObject(hBtm);
return bmp;
}
/// Checks that is in region.
public static bool IsInRegion(Region rgn, Point pt)
{
RectangleF[] rcts = rgn.GetRegionScans(new Matrix());
return IsInRectangles(rcts, pt);
}
public static bool IsInRectangles(RectangleF[] rcts, Point pt)
{
return IsInRectangles(rcts, (float)pt.X, (float)pt.Y);
}
/// Checks that is Point in Rectangles (Scans of Region).
public static bool IsInRectangles(RectangleF[] rcts, float x, float y)
{
for (int i = 0; i < rcts.Length; i++)
{
if (rcts[i].Contains(x, y))
{
return true;
}
}
return false;
}
public unsafe static void PasteToScreen(Bitmap bmp, Region rgn)
{
if (bmp == null || rgn == null)
return;
IntPtr hDc = GetDC(IntPtr.Zero);
Graphics g = Graphics.FromHdc(hDc);
RectangleF rctF = rgn.GetBounds(Graphics.FromHdc(hDc));
Rectangle rct = new Rectangle((int)rctF.X, (int)rctF.Y, (int)rctF.Width, (int)rctF.Height);
g.SetClip(rgn, CombineMode.Replace);
g.DrawImage((Image)bmp, rct);
DeleteDC(hDc); g.Dispose();
}
// NATIVE METHODS
[DllImport("gdi32.dll")]
public static extern int BitBlt(IntPtr srchDC, int srcX, int srcY, int srcW, int srcH,
IntPtr desthDC, int destX, int destY, RasterOperations op);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateDC(string lpDriverName, string lpDeviceName,
string lpOutput, string lpInitData);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern int GetClipBox(IntPtr hDC, ref RECT rectBox);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern int SelectClipRgn(IntPtr hDC, IntPtr hRgn);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
public static extern IntPtr SetTimer(IntPtr hWnd, int nIDEvent, int uElapse, TimerProc lpTimerFunc);
public delegate void TimerProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool KillTimer(IntPtr hwnd, int idEvent);
public enum RasterOperations : uint
{
SRCCOPY = 0x00CC0020,
SRCPAINT = 0x00EE0086,
SRCAND = 0x008800C6,
SRCINVERT = 0x00660046,
SRCERASE = 0x00440328,
NOTSRCCOPY = 0x00330008,
NOTSRCERASE = 0x001100A6,
MERGECOPY = 0x00C000CA,
MERGEPAINT = 0x00BB0226,
PATCOPY = 0x00F00021,
PATPAINT = 0x00FB0A09,
PATINVERT = 0x005A0049,
DSTINVERT = 0x00550009,
BLACKNESS = 0x00000042,
WHITENESS = 0x00FF0062
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public int Width
{
get { return right - left; }
}
public int Height
{
get { return bottom - top; }
}
}
}