屏幕捕获






4.77/5 (45投票s)
2006年1月31日
2分钟阅读

267620

3234
无需使用任何 Win32 API 调用即可捕获屏幕内容,仅使用 .NET (2.0) 类。
引言
关于屏幕截图的文章有很多,但其中大多数使用 Win32 API 函数,即使在 .NET 2.0 中也是如此,而这并不是必需的,因为 .NET 2.0 拥有实现该功能所需的所有类。
背景
通常需要获取整个屏幕或部分屏幕的截图。在我们的应用程序中,我们经常使用具有多个显示器的系统,这需要我们同时捕获所有显示器或分别捕获每个屏幕。请记住,虚拟屏幕是连接到系统的所有显示器的完整视图,主屏幕是主显示器的视图,而工作屏幕是相同的,但排除了任务栏。
使用代码
类 'ScreenCapture
' 提供了几个方法,允许捕获完整的虚拟屏幕、主屏幕、工作屏幕、特定窗体(完整或仅客户端区域)以及窗体中特定控件的内容。捕获的图像可以直接从您的代码中使用,也可以保存到文件中或打印。还有一个小助手类 'ImageFormatHandler
',用于在保存捕获的图像时处理不同的图形文件格式。
源代码
源代码文件包含两个描述的类,可以直接在您的代码中使用。它使用 Visual Studio 2005 构建。
我们的主要捕获方法如下所示
public Bitmap[] Capture( CaptureType typeOfCapture )
{
// used to capture then screen in memory
Bitmap memoryImage;
// number of screens to capture,
// will be updated below if necessary
int count = 1;
try
{
Screen[] screens = Screen.AllScreens;
Rectangle rc;
// setup the area to capture
// depending on the supplied parameter
switch ( typeOfCapture )
{
case CaptureType.PrimaryScreen:
rc = Screen.PrimaryScreen.Bounds;
break;
case CaptureType.VirtualScreen:
rc = SystemInformation.VirtualScreen;
break;
case CaptureType.WorkingArea:
rc = Screen.PrimaryScreen.WorkingArea;
break;
case CaptureType.AllScreens:
count = screens.Length;
typeOfCapture = CaptureType.WorkingArea;
rc = screens[0].WorkingArea;
break;
default:
rc = SystemInformation.VirtualScreen;
break;
}
// allocate a member for saving the captured image(s)
images = new Bitmap[count];
// cycle across all desired screens
for ( int index = 0; index < count; index++ )
{
if ( index > 0 )
rc = screens[index].WorkingArea;
// redefine the size on multiple screens
memoryImage = new Bitmap( rc.Width, rc.Height,
PixelFormat.Format32bppArgb );
using ( Graphics memoryGrahics =
Graphics.FromImage( memoryImage ) )
{
// copy the screen data
// to the memory allocated above
memoryGrahics.CopyFromScreen( rc.X, rc.Y,
0, 0, rc.Size, CopyPixelOperation.SourceCopy );
}
images[index] = memoryImage;
// save it in the class member for later use
}
}
catch ( Exception ex )
{
// handle any erros which occured during capture
MessageBox.Show( ex.ToString(), "Capture failed",
MessageBoxButtons.OK, MessageBoxIcon.Error );
}
return images;
}
使用的变量images
是该类的成员,类型为Bitmap[]
。此方法的参数typeOfCapture
是该类中定义的 enum
类型,用于选择实际应该捕获的内容。
还有另一种捕获方法,用于选择性地捕获控件、窗体或其客户端区域的内容。它的工作方式与上面显示的方法非常相似。
private Bitmap capture( Control window, Rectangle rc )
{
Bitmap memoryImage = null;
images = new Bitmap[1];
// Create new graphics object using handle to window.
using ( Graphics graphics = window.CreateGraphics() )
{
memoryImage = new Bitmap( rc.Width,
rc.Height, graphics );
using ( Graphics memoryGrahics =
Graphics.FromImage( memoryImage ) )
{
memoryGrahics.CopyFromScreen( rc.X, rc.Y,
0, 0, rc.Size, CopyPixelOperation.SourceCopy );
}
}
images[0] = memoryImage;
return memoryImage;
}
其他几种方法用于完成保存/打印捕获图像所需的所有工作,它们都在源代码的注释中进行了描述。
public void Save( String filename,
ImageFormatHandler.ImageFormatTypes format )
参数filename
保存所需的文件名以及完整路径,扩展名将根据参数format
选择的文件类型进行替换。
此方法根据选择的文件格式加载一些参数
ImageCodecInfo info;
EncoderParameters parameters =
formatHandler.GetEncoderParameters( format, out info );
这就是我们使用助手类ImageFormatHandler
进行所有操作的地方。我认为这是一个可以根据您自己的需要进行自定义的基础。
变更
实际示例已通过一些方法进行了更新,这些方法可用于从其他进程捕获屏幕;要做到这一点,必须使用原生代码。然后它不再是纯 .NET 2.0 解决方案。我们也没有使用分层窗体测试此解决方案,但在基本捕获方法中进行一些修改应该可以启用此功能。