C#从屏幕复制问题
首先,我知道已经有关于这方面的线索,但我似乎找不到适合我需要的答案,经过大约4个月的研究,我决定在这里问一个问题 对于一个项目,我需要做截图。这些屏幕截图是根据用户参数制作的,用户参数包括是否使用显示器或截图的拍摄区域。(这意味着屏幕截图可能仅由显示屏的一半左右组成。) 问题是,它很慢。。。 是的,我知道,如果我想做得更快,我必须使用这个库或那个directx等等。 但是:我既不知道directx,也找不到能够返回位图数据条带的开源lirary(realy更快)。 此外,我还尝试了一些使用directx制作屏幕截图的教程,但未能使其正常运行 关于性能方面,当只使用1个显示器时,性能实际上并没有那么差。(对于1440p分辨率,截图时间约为40ms) 真正糟糕的是DWM。(我猜是dwm)。 在制作屏幕截图时,除了在窗口周围拖动外,一切都正常。比如,在youtube上看视频就可以了。但是,当我开始在窗户周围走动时,它会慢得像地狱一样。在我截图时,拖动动画似乎被阻止了 现在请回答我的问题:C#从屏幕复制问题,c#,performance,screenshot,dwm,C#,Performance,Screenshot,Dwm,首先,我知道已经有关于这方面的线索,但我似乎找不到适合我需要的答案,经过大约4个月的研究,我决定在这里问一个问题 对于一个项目,我需要做截图。这些屏幕截图是根据用户参数制作的,用户参数包括是否使用显示器或截图的拍摄区域。(这意味着屏幕截图可能仅由显示屏的一半左右组成。) 问题是,它很慢。。。 是的,我知道,如果我想做得更快,我必须使用这个库或那个directx等等。 但是:我既不知道directx,也找不到能够返回位图数据条带的开源lirary(realy更快)。 此外,我还尝试了一些使用dir
- 有人知道这种行为和/或有解决方案吗
- 我的备选方案是什么(严肃的备选方案。我的意思是30毫秒备选方案中的3倍1440p)
public void makeScreenshot(int i)
{
if (DisplayList[i].UseDisplay)
{
// copy from screen into graphics
this.graphicsList[i].CopyFromScreen(Screen.AllScreens[DisplayList[i].DisplayNo].Bounds.X, AreaTop[i], 0, 0, sizeList[i], CopyPixelOperation.SourceCopy);
// bitmapData is filled with LockBits from Screenshotted Bmp
bitmapData[i] = this.bitmapList[i].LockBits(rect[i], ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// Pointer set to first pixel of Bitmap data
Iptr[i] = bitmapData[i].Scan0;
// Now Marshalcopy bitmapData to Pixel Array
Marshal.Copy(Iptr[i], Pixels[i], 0, Pixels[i].Length);
// Finaly unlock bits of Bitmap for next run
this.bitmapList[i].UnlockBits(bitmapData[i]);
}
}
有一个非常简单和稳定的解决方案,我已经用于屏幕捕获和直播,但它确实使用了一个外部库。也许你可以花几分钟来看看这个。我得到了6-15毫秒的1600x900屏幕截图。 所以,你需要-
private void _mirror_DesktopChange(object sender, DesktopMirror.DesktopChangeEventArgs e)
{
Trace.WriteLine(string.Format("Changed rect is {0},{1} ; {2}, {3} ({4})", new object[] { e.x1, e.y1, e.x2, e.y2, e.type }));
var perf = new Stopwatch();
perf.Start();
var bitmap = _mirror.GetScreen();
perf.Stop();
label1.Invoke(new Action<Int64>(i =>
{
pictureBox1.Image = bitmap;
label1.Text = i.ToString();
}), perf.ElapsedMilliseconds);
}
private void\u mirror\u DesktopChange(对象发送方,DesktopMirror.DesktopChangeEventArgs e)
{
Trace.WriteLine(string.Format(“更改的rect为{0},{1};{2},{3}({4})”),新对象[]{e.x1,e.y1,e.x2,e.y2,e.type});
var perf=新秒表();
性能启动();
var bitmap=_mirror.GetScreen();
性能停止();
标签1.Invoke(新操作(i=>
{
pictureBox1.Image=位图;
label1.Text=i.ToString();
}),性能ElapsedMills);
}
如果您关心性能,则不应使用GDI读取桌面
避免读取或写入显示器DC。虽然DWM支持,但由于性能下降,我们不建议使用它
虽然你没有这样做,但还是画画。除此之外,除了速度缓慢之外:
DirectDraw锁
- Windows 7:针对Windows 7的应用程序无法在DDRAW中调用锁定API来锁定主桌面视频缓冲区。这样做将导致错误,并且将返回主指针的NULL。即使未启用桌面窗口管理器合成,也会强制执行此行为。与Windows 7兼容的应用程序不得锁定要渲染的主视频缓冲区
- Windows Vista(默认):应用程序将能够获得主视频缓冲区上的锁定,因为传统应用程序依赖于此行为。运行应用程序将关闭桌面窗口管理器
你有代码示例吗?你使用的是像屏幕录制器库一样的库吗?将其附在主帖子上。你已经说过你不会为其他选择而烦恼,那么为什么要问呢?@JoePhilllips我没有说我不会尝试其他任何东西。我说我没有找到任何严肃的选择。如果有人知道一个好的,我不介意尝试一些图书馆或directx教程。你会注意到,尽可能地猛烈抨击DWM并不是一个好策略。商业屏幕录音机使用黑色Moocho艺术,他们不与任何人分享他们的秘密。买,不要建造。这是一件伟大的事情。在过去的半个小时里我一直在玩弄它。我很想使用它,但不幸的是,它不能与Windows10正常工作。(我想windows 8也会出现同样的错误)。屏幕上的一些白色平面没有正确记录。。。(它们在保存的位图上显示为黑色)我希望对于那些愿意使用此软件并尝试录制多个屏幕(或在我的情况下记录所有屏幕)的人,会有一个支持新操作系统的更新:在DesktopMirror::Load上有一个PrimaryScreen.Width分配。将其更改为下限和上限(您可以通过对所有屏幕进行分级来找到)将允许您投射所有屏幕。