在C#中捕获屏幕图像






4.58/5 (33投票s)
2002年10月12日
1分钟阅读

363710

13984
一篇关于使用Win32 API在C#中捕获屏幕的文章。
引言
我正在使用 C# 开发一个桌面共享类型的应用程序。我遇到的第一个问题是 C# 中没有太多工具可以截取桌面图像。经过一番研究,我了解到我需要使用 Win32 API 来为我的应用程序提供此功能。我创建了以下三个类来完成这项工作。
PlatformInvokeGDI32:
此类包含此应用程序中使用的所有 GDI32.dll API。PlatformInvokeUSER32:
此类包含所有 User32.dll API。CaptureScreen:
在这个类中,我提供了一个简单的静态函数GetDesktopImage
,它使用PlatformInvokeGDI32
和PlatformInvokeUSER32
中提供的 API 截取屏幕图像,并将其作为位图返回。
您可以很容易地将这些类放置在您的 C# 应用程序中。只需将以下代码复制并粘贴到您的 C# 项目中,无需进行任何更改。如果您想使用附带的源文件,您可以将 CaptureScreen
命名空间添加到您的项目中,或者只需将这些类中的 CaptureScreen
命名空间更改为您的项目命名空间即可,就完成了。
美丽的源代码
/// <summary>
/// This class shall keep the GDI32 APIs used in our program.
/// </summary>
public class PlatformInvokeGDI32
{
#region Class Variables
public const int SRCCOPY = 13369376;
#endregion
#region Class Functions<br>
[DllImport("gdi32.dll",EntryPoint="DeleteDC")]
public static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll",EntryPoint="DeleteObject")]
public static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll",EntryPoint="BitBlt")]
public static extern bool BitBlt(IntPtr hdcDest,int xDest,
int yDest,int wDest,int hDest,IntPtr hdcSource,
int xSrc,int ySrc,int RasterOp);
[DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,
int nWidth, int nHeight);
[DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport ("gdi32.dll",EntryPoint="SelectObject")]
public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp);
#endregion
#region Public Constructor
}
/// <summary>
/// This class shall keep the User32 APIs used in our program.
/// </summary>
public class PlatformInvokeUSER32
{
#region Class Variables
public const int SM_CXSCREEN=0;
public const int SM_CYSCREEN=1;
#endregion
#region Class Functions
[DllImport("user32.dll", EntryPoint="GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll",EntryPoint="GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll",EntryPoint="GetSystemMetrics")]
public static extern int GetSystemMetrics(int abc);
[DllImport("user32.dll",EntryPoint="GetWindowDC")]
public static extern IntPtr GetWindowDC(Int32 ptr);
[DllImport("user32.dll",EntryPoint="ReleaseDC")]
public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc);
#endregion
}
/// <summary>
/// This class shall keep all the functionality
/// for capturing the desktop.
/// </summary>
public class CaptureScreen
{
#region Class Variable Declaration
protected static IntPtr m_HBitmap;
#endregion
///
/// This class shall keep all the functionality for capturing
/// the desktop.
///
public class CaptureScreen
{
#region Public Class Functions
public static Bitmap GetDesktopImage()
{
//In size variable we shall keep the size of the screen.
SIZE size;
//Variable to keep the handle to bitmap.
IntPtr hBitmap;
//Here we get the handle to the desktop device context.
IntPtr hDC = PlatformInvokeUSER32.GetDC
(PlatformInvokeUSER32.GetDesktopWindow());
//Here we make a compatible device context in memory for screen
//device context.
IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC);
//We pass SM_CXSCREEN constant to GetSystemMetrics to get the
//X coordinates of the screen.
size.cx = PlatformInvokeUSER32.GetSystemMetrics
(PlatformInvokeUSER32.SM_CXSCREEN);
//We pass SM_CYSCREEN constant to GetSystemMetrics to get the
//Y coordinates of the screen.
size.cy = PlatformInvokeUSER32.GetSystemMetrics
(PlatformInvokeUSER32.SM_CYSCREEN);
//We create a compatible bitmap of the screen size and using
//the screen device context.
hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap
(hDC, size.cx, size.cy);
//As hBitmap is IntPtr, we cannot check it against null.
//For this purpose, IntPtr.Zero is used.
if (hBitmap!=IntPtr.Zero)
{
//Here we select the compatible bitmap in the memeory device
//context and keep the refrence to the old bitmap.
IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject
(hMemDC, hBitmap);
//We copy the Bitmap to the memory device context.
PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0,size.cx,size.cy, hDC,
0, 0,PlatformInvokeGDI32.SRCCOPY);
//We select the old bitmap back to the memory device context.
PlatformInvokeGDI32.SelectObject(hMemDC, hOld);
//We delete the memory device context.
PlatformInvokeGDI32.DeleteDC(hMemDC);
//We release the screen device context.
PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32.
GetDesktopWindow(), hDC);
//Image is created by Image bitmap handle and stored in
//local variable.
Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap);
//Release the memory to avoid memory leaks.
PlatformInvokeGDI32.DeleteObject(hBitmap);
//This statement runs the garbage collector manually.
GC.Collect();
//Return the bitmap
return bmp;
}
//If hBitmap is null, retun null.
return null;
}
#endregion
}
//This structure shall be used to keep the size of the screen.
public struct SIZE
{
public int cx;
public int cy;
}
结论
包含此代码的演示应用程序展示了这些类的用法。它是一个非常简单的 Windows 应用程序,其中包含一个简单的表单,该表单具有一个菜单和一个PictureBox控件。菜单的“Capture Screen”菜单项用于截取屏幕并将其分配给PictureBox控件的图像属性。我希望您喜欢这段代码。我已经对这段代码的每一行都进行了注释,使其易于理解。如果仍然有任何不清楚的地方,请告诉我。祝你好运!