最近工做 中有个需求是抓取桌面截图, 这里的桌面是指点了“显示桌面”以后看到的桌面, 截图内容包括桌面背景和图标以及任务栏,以下图:
注意需求是:即便当前其余窗口盖在咱们的桌面上,咱们要求抓取到的内容也是这些窗口背后的桌面。windows
思考怎么样才能在程序运行时,动态抓取该截图?
大概想了些方法:
(1) 经过Desktop DC, 而后BitBlt
点评: 经过这种方法抓取到的截图是当前桌面的全部窗口,包括其余当前打开显示的窗口 , 这不是咱们所指望的。
另外咱们也不可能在须要截图时最小化全部窗口, 截完了再还原。
(2)经过注册表获取桌面壁纸保存的地方
点评:获取到该壁纸, 没有图标和任务栏, 也不是咱们所指望的。
(3)经过DWM特性来获取
点评: Vista后的Desktop Window Manager(DWM)特性,可让咱们经过DwmRegisterThumbnail,DwmUpdateThumbnailProperties等API实时显示某个窗口的截图。惋惜获取到的内容只能显示在咱们预约义的窗口里, 可是咱们无法获取里面的内容。另外这个特性只有Vista以后才支持, XP系统怎么办?
(4)经过Magnification来获取
点评:咱们能够经过系统的放大镜技术,
过滤掉盖在桌面上的其余窗口(MagSetWindowFilterList
),而后经过MagSetImageScalingCallback
拦截内容。该技术的问题一是过滤窗口的个数限制, 另外也只能适用于Vista以后。
(5)经过API Hook技术
点评:经过API Hook技术咱们能够动态拦截桌面窗口DC的绘画动做,这样就能够拦截或是合成窗口内容了。可是一来这样作比较复杂, 稳定性也很难保证,另外也有杀鸡用牛刀的感受。
(6)经过PrintWindow技术
点评:PrintWindow API内部经过WM_PRINTCLIENT和WM_PRINT来获取窗口截图, 这个API在XP时代工做的不是很好,可是在Vista以后已经比较稳定了。
咱们最后选择经过PrintWindow API来获取桌面截图, 大概过程以下:
a. 获取桌面窗口(Program Manager)的内容
b. 获取TaskBar窗口的位置和内容
c. 把TaskBar窗口内容和桌面内容合成, 贴在正确的位置
这里说一下要注意的一些问题:
a . 注意窗口的层次
Aero模式下, Program Manager窗口只包含背景图片, 图标列表在WorkerW窗口下:
Basic模式下窗口内容都在Program Manager窗口下:
b. 注意多显示器的状况, 多显示器时除了主显示器,其余桌面是没有任务栏的
c. 注意任务栏的位置, 任务栏是能够Dock到任何地方而且可以隐藏的,不要hard code在下面了。测试
d. XP下对ProgramManager窗口调用PrintWindow会有刷新问题。一直没有好的解决方案, 因此对XP勉强采用第一种DC的方式了。
所以, 我到如今尚未找到完整解决咱们这个问题的方法, 不知道你们有没有好的思路?