Windows桌面共享中一些常见的抓屏技术

本篇博客内容是属于转载的,原文地址:windows

http://www.cppblog.com/weiym/archive/2013/12/01/204536.aspx缓存

 

1. BitBltide

 

我想作Windows开发应该都知道这个API, 它能实现DC间的内容拷贝, 若是咱们把源DC指定成Monitor DC或是桌面DC, 它就能实现抓屏功能。函数

对于经过这种方式的抓屏, 有2点须要特别提醒:学习

a. 在XP下咱们能够经过最后的拷贝标志来控制是否拷贝layered window, 只有SRCCPY表示拷贝内容不包含layered window, 若是是SRCCPY | CAPTUREBLT表示拷贝包括Layered window在内的全部窗口。 这个标志在Vista以后的系统(win7/win8),开启DWM的状况下, 已经失效, 由于这种状况下全部的窗口都是layered window.
b. 这种方式的抓屏在 Vista以后, 开启DWM的状况下, 抓屏速度很是慢(30ms +), 具体缘由不知道是由于系统没有缓存整个屏幕的数据仍是GPU向内存拷贝数据太慢了, 有知道的朋友能够提示下。
 

2. Mirror driver测试

 

这种方法应该是Win8以前最高效的抓屏方法, 也是微软推荐的远程桌面共享方案,它经过建立虚拟镜像驱动, 直接获取最终屏幕变化数据。优化

该方法也有一些缺点:编码

a. 涉及到驱动安装, 技术难度大, 系统权限要求也高
b. Win8 上该方案已经失效, 可是仍是有方法的, 参见 Remote Display Drivers

 

3. GDI hookspa

 

这种方法应该说是XP时代比较流行的抓屏方法, 由于全部的绘制都是经过GDI32.dll中的绘图函数来实现的, 因此咱们只要拦截了这些函数, 系统的全部绘制就都让咱们控制了。这种方法应该来讲也是一种挺高效的抓屏方法,屏幕的变化也都能让咱们拦截到, 同时由于好多绘图函数是以矢量方式实现的,全部抓到的数据包很是小, 即便在低带宽下也效果挺好。操作系统

下面是该方法的一些缺点:

a. Hook技术自己就有其复杂性和不稳定性, 尤为是Hook全部进程
b. Vista只有愈来愈多程序采用D2D/D3D绘制, GDI Hook对这些绘制无能为力。
c. Vista以后UAC打开的状况下, 若是咱们的程序权限不够高, Hook不到更高权限的程序。
 

4. Windows Media API

 

Windows Media 9.0 支持用Windows Media Encoder 9 API来抓屏。它有一个编码器叫Windows Media Video 9 Screen codec,特别为抓屏优化过。Windows Media Encoder API提供了一个IWMEncoder2接口能够用来高效地捕捉屏幕图像。

由于对这组API不熟, 这种抓屏方法我也没尝试过, 具体可见Various methods for capturing the screen, 感受这种方法的最大缺点是用户机器须要安装Windows Media Encoder 9。
 

5. DirectX
 

每一个DirectX程序都包含一个被咱们称做缓冲的内存区域,其中保存了和该程序有关的显存内容,这在程序中被称做后台缓冲(Back Buffer),有些程序有不止一个的后台缓冲。还有一个缓冲,在默认状况下每一个程序均可以访问-前台缓冲。前台缓冲保存了和桌面相关的显存内容,实质上就是屏幕图像。 咱们的程序经过访问前台缓冲就能够捕捉到当前屏幕的内容。上面的列子中也包含该方法的实现, 是基于DirectX9的,咱们能够参考下, 据我测试该方法在DWM打开的状况下抓整屏也要30ms左右。Vista以后的DirectX 10/11相对于DirectX 9 已经发生很是大的变化, 直接用新的接口上面的代码未必能正常工做。


6. PrintWindow

 

该方法自己不能直接作为一种抓屏方法, 可是有时候咱们要获取某个窗口的内容, 即便他被其余窗口覆盖着, 这时候这个函数就颇有用。该方该调用法的原理是经过给目标窗口发送WM_PRINT或是WM_PRINTCLIENT消息, 因此若是目标窗口没有响应, 该调用可能会阻塞抓屏线程, 这种状况下抓屏前最好先用SendMessageTimeout检测目标窗口是否有响应。另外该方法也抓不到D3D窗口的内容。


7. DWM/Dxgi hook

 

Vista以后微软放弃了XP时代的XPDM, 采用了全新的WDDM视屏驱动模型, 如今Win8.1上已是WDDM1.3.

Vista以后底层全部的渲染都是基于D3D技术, 另外咱们也知道系统在DWM.exe里进行窗口边框的绘画和合成, 因此理论上咱们能够经过HOOK DWM/D3D/DXGI,拦截到整个系统的屏幕内容。固然做为一种Hook技术, 它也有上面GDI Hook相似的问题。
 

8. Magnification

 

这组API是微软Vista以后开放给咱们开发放大镜程序的, 它里面提供了一个API让咱们拦截到显示的内容, 惋惜的是这个关键的API  MagSetImageScalingCallback 微软已经宣布做废。另外该方式的抓屏效率也不高, 整屏须要60 ms 左右。
 

9. Desktop Duplication  

 

这是微软Win8 上宣布放弃Mirror driver以后推荐采用的抓屏技术, 所有基于D3D/DXGI技术, 效率很是高, 而且包含变化区域和屏幕鼠标光标。它的缺点是无法抓取某个窗口的内容 。
 

10. GetWindowDC 


该方法和PrintWindow相似,可是它没有PrintWindow的权限问题, 也没有超时问题。
这种抓屏方法在Win7/Win8  DWM打开的状况下抓屏,结果会颠覆咱们XP时代的知识, 由于即便窗口被覆盖, 它也能够正确抓取到被覆盖窗口下的内容, WebRTC正是用这种方式来Share  Application的。
它的主要问题是有些窗口抓到的内容不包含非客户区,有些窗口好比任务栏的Thumbnail窗口会抓不到内容。

 

最后简单总结下 , 咱们能够看到Windows系统上基本没有一种通用的抓屏技术能够高效的抓取全部的系统(XP/Win7/Win8), 很大一部缘由是操做系统的显示驱动模型在从XPDM向WDDM转变, 应用层的API也在从GDI向D3D转变 。 相对于Linux的稳定, Window的不断发展和进步, 对开发人员到底是喜是悲?

 

另外还有一篇博文值得参考学习,该博文仔细的介绍了几种抓屏的方式:

http://blog.csdn.NET/henry19850318/article/details/5732106

相关文章
相关标签/搜索