昨天,因为需要一个截屏的功能所以自己就写了一下。第一版是一个单纯的利用.net类库来实现的屏幕方式。
static public void PrintSystemScreen (string file) {
if (string.IsNullOrEmpty(file)) {
// Create a random file name by GUID and set the saved
// directory at current directory.
file = Guid.NewGuid().ToString();
}
// Create a bitmap for save
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppPArgb);
// Create a graphic for drawing from bmp
Graphics screenG = Graphics.FromImage(bmp);
screenG.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
ImageParams imgParam = new ImageParams(file);
bmp.Save(imgParam.FilePath, imgParam.CodeInfo, imgParam.EncoderParam);
}
if (string.IsNullOrEmpty(file)) {
// Create a random file name by GUID and set the saved
// directory at current directory.
file = Guid.NewGuid().ToString();
}
// Create a bitmap for save
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppPArgb);
// Create a graphic for drawing from bmp
Graphics screenG = Graphics.FromImage(bmp);
screenG.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
ImageParams imgParam = new ImageParams(file);
bmp.Save(imgParam.FilePath, imgParam.CodeInfo, imgParam.EncoderParam);
}
第二版,我加入了根据给出的应用程序主窗口去截取界面的功能,使用Win32 Api来实现:
/**//// <summary>
/// GeneralScreen include serval functions.
/// Capture single screenshot.
/// Capture application screenshot.
/// !Capture web page screenshot.
/// </summary>
static public class GeneralScreen {
/**//// <summary>
/// Capturing the current screen operation then save
/// image to the indicated file.
/// </summary>
/// <param name="file"></param>
static public void PrintSystemScreen (string file) {
IntPtr screenHandle = NativeMethods.GetDesktopWindow();
Capture(screenHandle, file);
}
/**//// <summary>
/// Create a random file name by GUID under the runtime directory.
/// </summary>
static public void PrintSystemScreen () {
PrintSystemScreen(null);
}
/**//// <summary>
/// Capturing the indicated application window operation then save
/// image to the indicated file. If the file parameter not set, function will
/// create a random file name by GUID under the runtime directory.
/// </summary>
/// <param name="handle">window's handle</param>
/// <param name="file">target image file</param>
static public void PrintApplicationScreen (IntPtr handle, string file) {
if (NativeMethods.SetForegroundWindow(handle)) {
Capture(handle, file);
}
}
Helper#region Helper
/**//// <summary>
/// Capture the indicated region screenshot by the indicated window.
/// </summary>
/// <param name="handle">indicated window handle</param>
/// <param name="file">save image file name</param>
static private void Capture (IntPtr handle, string file) {
// Testing source handle
if (handle != IntPtr.Zero) {
NativeMethods.RECT srcRect;
// Get the source window's information
if (NativeMethods.GetWindowRect(handle, out srcRect)) {
int width = srcRect.Right - srcRect.Left;
int height = srcRect.Bottom - srcRect.Top;
Capture(srcRect.Left, srcRect.Top, width, height, file);
}
}
}
/**//// <summary>
/// Capture the screenshot by coordinate from display memory.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="file"></param>
static private void Capture (int x, int y, int width, int height, string file) {
System.Drawing.Image targetImg;
IntPtr displayDC = IntPtr.Zero;
IntPtr compatibleDC = IntPtr.Zero;
IntPtr bmp = IntPtr.Zero;
try {
displayDC = NativeMethods.CreateDC("DISPLAY",
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
if (displayDC == IntPtr.Zero) {
throw new Exception("CreateDC failed!");
}
compatibleDC = NativeMethods.CreateCompatibleDC(displayDC);
if (compatibleDC == IntPtr.Zero) {
throw new Exception("CreateCompatibleDC failed!");
}
bmp = NativeMethods.CreateCompatibleBitmap(displayDC, width, height);
// set DC relate to bmp
if (NativeMethods.SelectObject(compatibleDC, bmp) == IntPtr.Zero) {
throw new Exception("CreateCompatibleBitmap failed");
}
if (0 == NativeMethods.BitBlt(compatibleDC, 0, 0, width, height,
displayDC, x, y,
0xcc0020)) {
throw new Exception("BitBlt failed");
}
targetImg = System.Drawing.Image.FromHbitmap(bmp);
// Save image
//
if (string.IsNullOrEmpty(file)) {
// Create a random file name by GUID and set the saved
// directory at current directory.
file = Guid.NewGuid().ToString();
}
ImageParams imgParam = new ImageParams(file);
targetImg.Save(imgParam.FilePath, imgParam.CodeInfo, imgParam.EncoderParam);
} finally {
NativeMethods.DeleteDC(displayDC);
NativeMethods.DeleteDC(compatibleDC);
NativeMethods.DeleteObject(bmp);
}
}
#endregion
}
/**//// <summary>
/// The nativeMethods includes the win32 api for the others
/// class calling.
/// </summary>
internal static class NativeMethods {
// Methods
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern int BitBlt (IntPtr destDC, int xDest, int yDest, int width, int height, IntPtr sourceDC, int xSource, int ySource, uint rasterOperation);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateCompatibleBitmap (IntPtr dc, int width, int height);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateCompatibleDC (IntPtr dc);
[DllImport("gdi32.dll", EntryPoint = "CreateDCW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateDC (string driver, IntPtr device, IntPtr output, IntPtr devMode);
[DllImport("gdi32.dll", ExactSpelling = true)]
internal static extern int DeleteDC (IntPtr dc);
[DllImport("gdi32.dll", ExactSpelling = true)]
internal static extern int DeleteObject (IntPtr gdiObject);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr SelectObject (IntPtr dc, IntPtr gdi);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetWindowRect (IntPtr hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetForegroundWindow (IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow ();
}
/// GeneralScreen include serval functions.
/// Capture single screenshot.
/// Capture application screenshot.
/// !Capture web page screenshot.
/// </summary>
static public class GeneralScreen {
/**//// <summary>
/// Capturing the current screen operation then save
/// image to the indicated file.
/// </summary>
/// <param name="file"></param>
static public void PrintSystemScreen (string file) {
IntPtr screenHandle = NativeMethods.GetDesktopWindow();
Capture(screenHandle, file);
}
/**//// <summary>
/// Create a random file name by GUID under the runtime directory.
/// </summary>
static public void PrintSystemScreen () {
PrintSystemScreen(null);
}
/**//// <summary>
/// Capturing the indicated application window operation then save
/// image to the indicated file. If the file parameter not set, function will
/// create a random file name by GUID under the runtime directory.
/// </summary>
/// <param name="handle">window's handle</param>
/// <param name="file">target image file</param>
static public void PrintApplicationScreen (IntPtr handle, string file) {
if (NativeMethods.SetForegroundWindow(handle)) {
Capture(handle, file);
}
}
Helper#region Helper
/**//// <summary>
/// Capture the indicated region screenshot by the indicated window.
/// </summary>
/// <param name="handle">indicated window handle</param>
/// <param name="file">save image file name</param>
static private void Capture (IntPtr handle, string file) {
// Testing source handle
if (handle != IntPtr.Zero) {
NativeMethods.RECT srcRect;
// Get the source window's information
if (NativeMethods.GetWindowRect(handle, out srcRect)) {
int width = srcRect.Right - srcRect.Left;
int height = srcRect.Bottom - srcRect.Top;
Capture(srcRect.Left, srcRect.Top, width, height, file);
}
}
}
/**//// <summary>
/// Capture the screenshot by coordinate from display memory.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="file"></param>
static private void Capture (int x, int y, int width, int height, string file) {
System.Drawing.Image targetImg;
IntPtr displayDC = IntPtr.Zero;
IntPtr compatibleDC = IntPtr.Zero;
IntPtr bmp = IntPtr.Zero;
try {
displayDC = NativeMethods.CreateDC("DISPLAY",
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
if (displayDC == IntPtr.Zero) {
throw new Exception("CreateDC failed!");
}
compatibleDC = NativeMethods.CreateCompatibleDC(displayDC);
if (compatibleDC == IntPtr.Zero) {
throw new Exception("CreateCompatibleDC failed!");
}
bmp = NativeMethods.CreateCompatibleBitmap(displayDC, width, height);
// set DC relate to bmp
if (NativeMethods.SelectObject(compatibleDC, bmp) == IntPtr.Zero) {
throw new Exception("CreateCompatibleBitmap failed");
}
if (0 == NativeMethods.BitBlt(compatibleDC, 0, 0, width, height,
displayDC, x, y,
0xcc0020)) {
throw new Exception("BitBlt failed");
}
targetImg = System.Drawing.Image.FromHbitmap(bmp);
// Save image
//
if (string.IsNullOrEmpty(file)) {
// Create a random file name by GUID and set the saved
// directory at current directory.
file = Guid.NewGuid().ToString();
}
ImageParams imgParam = new ImageParams(file);
targetImg.Save(imgParam.FilePath, imgParam.CodeInfo, imgParam.EncoderParam);
} finally {
NativeMethods.DeleteDC(displayDC);
NativeMethods.DeleteDC(compatibleDC);
NativeMethods.DeleteObject(bmp);
}
}
#endregion
}
/**//// <summary>
/// The nativeMethods includes the win32 api for the others
/// class calling.
/// </summary>
internal static class NativeMethods {
// Methods
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern int BitBlt (IntPtr destDC, int xDest, int yDest, int width, int height, IntPtr sourceDC, int xSource, int ySource, uint rasterOperation);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateCompatibleBitmap (IntPtr dc, int width, int height);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateCompatibleDC (IntPtr dc);
[DllImport("gdi32.dll", EntryPoint = "CreateDCW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr CreateDC (string driver, IntPtr device, IntPtr output, IntPtr devMode);
[DllImport("gdi32.dll", ExactSpelling = true)]
internal static extern int DeleteDC (IntPtr dc);
[DllImport("gdi32.dll", ExactSpelling = true)]
internal static extern int DeleteObject (IntPtr gdiObject);
[DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr SelectObject (IntPtr dc, IntPtr gdi);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetWindowRect (IntPtr hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetForegroundWindow (IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow ();
}
在这里我用了一个辅助的类ImageParam,这个类可以根据给出的文件名自己识别需要生成什么格式的图片文件。
完整的Demo工程从这里下载