1. BitBlt

我想做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 上该方案已经失效

3. GDI hook

这种方法应该说是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的,我们可以参考下。
Vista之后的DirectX 10/11相对于DirectX 9 已经发生非常大的变化, 直接用新的接口上面的代码未必能正常工作, 但是COM的优点就是我们可以在新的组件中依然调用老的接口。
 
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的不断发展和进步, 对开发人员究竟是喜是悲?

Windows桌面共享中一些常见的抓屏技术的更多相关文章

  1. Windows抓屏技术

    Windows桌面共享中一些常见的抓屏技术 1. BitBlt   我想做Windows开发应该都知道这个API, 它能实现DC间的内容拷贝, 如果我们把源DC指定成Monitor DC或是桌面DC, ...

  2. 基于GDI和D3D的抓屏技术

    GDI32Api.Direct3D屏幕截图 最近因为工作需要,认真研究了一下屏幕截图的方法. 最主要的方法有两种,一.调用windows GDI32 API函数.二.使用DirectX9.0来实现. ...

  3. 4┃音视频直播系统之浏览器中通过 WebRTC 进行桌面共享

    一.共享桌面原理 共享桌面在直播系统中是一个必备功能 共享者:每秒钟抓取多次屏幕,每次抓取的屏幕都与上一次抓取的屏幕做比较,取它们的差值,然后对差值进行压缩:如果是第一次抓屏或切幕的情况,即本次抓取的 ...

  4. VMware下的Linux系统中Windows的共享目录,不支持创建软连接

    [问题]  在编译VMware下的Linux系统对从Windows中共享过来的文件,进行编译的时候,遇到:  ln: creating symbolic link XXXXXX : Operation ...

  5. 在 linux 中利用samba访问windows的共享

    只是介绍一些最基本的应用吧, 有些命令可能要求输入用户的密码 1. 首先要安装 samba 这个套件, 若只是访问windows中的共享的话, 可以只装 samba-client 就好了. 2. 在第 ...

  6. VMware10中的CentOS6.5命令行安装VMwaretools工具启用windows与虚拟机中Linux系统的共享目录

    VMware10中的CentOS6.5命令行安装VMwaretools工具启用windows与虚拟机中Linux系统的共享目录 一.描述 系统描述:win7旗舰版64位系统+VMware Workst ...

  7. [windows]窗口文件夹中使用常见任务

    文件夹中使用常见任务,如截图所示增加红色框部分. 设置步骤: 我的电脑--〉右键--〉属性--〉高级选项--〉性能设置--〉自定义:勾选在文件夹中使用常见任务.

  8. 盘点Windows 8.1中隐藏着的25个秘密功能

    Windows 8.1正式版问世,带来了众多大家早已耳熟能详的“开始按钮”.“分屏显示”等功能.事实上,Windows 8.1贴心的设计细节有很多,多数细节隐藏于系统中某个不起眼的角落,科技网站PC ...

  9. 在远程桌面服务中配置RD网关直接访问内网

    原文地址:http://wangchunhai.blog.51cto.com/225186/1139388/ 远程桌面网关(RD 网关)是一项角色服务,使授权远程用户可以从任何连接到 Internet ...

随机推荐

  1. Windows netstat 查看端口、进程占用

    目标:在Windows环境下,用netstat命令查看某个端口号是否占用,为哪个进程所占用. (1)查看该端口被那个PID所占用;方法一:有针对性的查看端口,在命令行下,使用命令netstat –an ...

  2. ZooKeeper事务日志记录器SyncRequestProcessor

    SyncRequestProcessor作为一个ZooKeeper中的一个关键线程(ZooKeeperCriticalThread),是ZooKeeper请求处理链中的事务日志记录处理器,其主要用来将 ...

  3. grep及正则表达式

    文本搜索工具:grep,egrep,fgrep GREP介绍 grep: 根据模式条件搜索文本,并将符合模式的文本行显示出来.  过滤条件:文本字符和正则表达式的元字符组合而成匹配条件 以正则表达式的 ...

  4. winfrom调用FastReport模板

    '存放模板的路径 If Dir(Application.StartupPath & "\ReportsFile\HB\01\IN.frx", FileAttribute.N ...

  5. Ubuntu 16.04 下使用Xampp

    Ubuntu 16.04 下使用Xampp 什么是Xampp? XAMPP(Apache+MySQL+PHP+PERL) 是一个功能强大的建站集成软件包.这个软件包原来的名字是 LAMPP,但是为了避 ...

  6. 修改centos启动项

    centos7下修改启动项在路径/etc/grub.d/文件路径下,修改完成之后需要运行命令 grub2-mkconfig --output=/boot/grub2/grub.cfg

  7. Python 10 —— 杂

    Python 10 —— 杂 科学计算 NumPy:数组,数组函数,傅里叶变换 SciPy:依赖于NumPy,提供更多工具,比如绘图 绘图 Matplitlib:依赖于NumPy和Tkinter

  8. 黑马程序员-NSDictionary和NSMutableDictionary

    NSDictionary和NSMutableDictionary:通过key和value进行对应,进行存储元素,能够方便提取所需的元素.key是不能够重复出现,但是value能够重复出现.NSDict ...

  9. CrossApp入门简介

    来自9miao社区的CrossApp号称可以极大的简化移动应用的开发,因为开源的时间不长,有效的资料不多. 官方网站: http://crossapp.9miao.com/ 环境搭建说明:http:/ ...

  10. 嵌入式linux开发环境构建

    2.1硬件环境构建 2.1.1主机与目标板结合的交叉开发模式 在主机上编辑.编译软件,然后再目标办上运行.验证程序. 对于S3C2440.S3C2410开发板,进行嵌入式Linux开发时一般可以分为以 ...