C#拍摄屏幕截图的最快方式是什么?

C#拍摄屏幕截图的最快方式是什么?,c#,.net,graphics,C#,.net,Graphics,我正在实现一个功能,将采取屏幕截图重复和输出脏矩形之间的两个不同的镜头,然后发送重新绘制窗口中的屏幕 目前我可以让它以20~30FPS的速度运行。这已经可以接受了。但后来我制定了一个基准,并衡量了它的表现。发现Graphics.CopyFromScreen()占用了50%的处理时间。(是的,即使在最坏的情况下,它仍然需要比查找所有脏矩形更长的时间)然后我使用本机API实现BitBlt(),没有得到任何改进 我知道在这种情况下,可能没有任何实际理由使其速度超过30FPS。我只是想知道,有没有更快的

我正在实现一个功能,将采取屏幕截图重复和输出脏矩形之间的两个不同的镜头,然后发送重新绘制窗口中的屏幕

目前我可以让它以20~30FPS的速度运行。这已经可以接受了。但后来我制定了一个基准,并衡量了它的表现。发现
Graphics.CopyFromScreen()
占用了50%的处理时间。(是的,即使在最坏的情况下,它仍然需要比查找所有脏矩形更长的时间)然后我使用本机API实现
BitBlt()
,没有得到任何改进

我知道在这种情况下,可能没有任何实际理由使其速度超过30FPS。我只是想知道,有没有更快的方法来拍摄屏幕截图


谢谢。

查看
CopyFromScreen()的替代方法。
检查。请注意,
Graphics.CopyFromScreen()
本身调用API
BitBlt()
从屏幕复制,您可以使用Reflector检查源代码。

这与几年前提出的问题非常相似:。这个问题是,能力是否可以用来获得更好的表现

大家的共识是,它可能不会提供任何性能提升,TightVNC通过欺骗很快做到了这一点。它使用的驱动程序不必使用.NET正在使用的API


在某个时候,我记得我看过的源代码,我相信他们使用了directx的捕获功能。我不认为你能超过30 fps那么快,而且大多数时候甚至不能超过30 fps。我不确定这是否是camstudio用来确定什么时候发生了变化或实际捕获机制的钩子的问题。

对于使用此线程的人,我提出了以下解决方案:

使用SharpDX;
使用SharpDX.Direct3D11;
使用SharpDX.DXGI;
使用制度;
使用系统诊断;
使用系统图;
使用系统、绘图、成像;
使用System.IO;
使用System.Threading.Tasks;
您将需要软件包SharpDX和SharpDX.Direct3D11

公共类ScreenStateLogger
{
专用字节[]_上一屏幕;
私家车运行,初始化;
公共整数大小{get;私有集;}
公共ScreenStateLogger()
{
}
公开作废开始()
{
_run=true;
var factory=new Factory1();
//获取第一个适配器
var adapter=factory.GetAdapter1(0);
//从适配器获取设备
var设备=新的SharpDX.Direct3D11.device(适配器);
//获取适配器的前缓冲区
var output=adapter.GetOutput(0);
var output1=output.QueryInterface();
//要捕获的桌面的宽度/高度
int width=output.Description.DesktopBounds.Right;
int height=output.Description.DesktopBounds.Bottom;
//创建可由CPU访问的临时纹理
var textureDesc=新的texture2ddedescription
{
CpuAccessFlags=CpuAccessFlags.Read,
BindFlags=BindFlags.None,
格式=Format.B8G8R8A8_UNorm,
宽度=宽度,
高度=高度,
OptionFlags=ResourceOptionFlags.None,
MIP级别=1,
ArraySize=1,
SampleDescription={Count=1,Quality=0},
用法=ResourceUsage.Staging
};
var screenTexture=新的Texture2D(设备,textureDesc);
Task.Factory.StartNew(()=>
{
//复制输出
使用(var duplicatedOutput=output1.DuplicateOutput(设备))
{
while(_run)
{
尝试
{
SharpDX.DXGI.Resource屏幕资源;
OutputDuplicateFrameInformation duplicateFrameInformation;
//尝试在给定的时间毫秒内获得重复帧
duplicatedOutput.AcquireNextFrame(5,输出duplicateFrameInformation,输出screenResource);
//将资源复制到CPU可以访问的内存中
使用(var screenTexture2D=screenResource.QueryInterface())
device.ImmediateContext.CopyResource(screenTexture2D,screenTexture);
//获取桌面捕获纹理
var mapSource=device.ImmediateContext.MapSubresource(screenTexture,0,MapMode.Read,SharpDX.Direct3D11.MapFlags.None);
//创建图形。位图
使用(var位图=新位图(宽度、高度、像素格式.Format32bppArgb))
{
var boundsRect=新矩形(0,0,宽度,高度);
//将屏幕捕获纹理中的像素复制到GDI位图
var mapDest=bitmap.LockBits(boundsRect,ImageLockMode.WriteOnly,bitmap.PixelFormat);
var sourcePtr=mapSource.DataPointer;
var destPtr=mapDest.Scan0;
对于(int y=0;y