C# 在Windows Vista、Windows 7中拍摄屏幕截图,应用程序区域外有透明区域

C# 在Windows Vista、Windows 7中拍摄屏幕截图,应用程序区域外有透明区域,c#,windows-7,gdi+,gdi,windows-vista,C#,Windows 7,Gdi+,Gdi,Windows Vista,我正在尝试拍摄一个应用程序的屏幕截图,我希望矩形中不属于应用程序区域的部分是透明的。例如,在标准windows应用程序上,我希望使圆角透明 我编写了一个快速的测试应用程序,可以在XP(或关闭aero的vista/Windows7)上运行: 当我在XP(或关闭Aero的Vista/Windows7)上运行这个测试应用程序时,我得到了类似的结果,这非常好,因为我可以从中找到一个xor掩码,以后可以与BitBlt一起使用 已删除死掉的Imageshack链接-屏幕截图 问题是,在Vista或启用Aer

我正在尝试拍摄一个应用程序的屏幕截图,我希望矩形中不属于应用程序区域的部分是透明的。例如,在标准windows应用程序上,我希望使圆角透明

我编写了一个快速的测试应用程序,可以在XP(或关闭aero的vista/Windows7)上运行:

当我在XP(或关闭Aero的Vista/Windows7)上运行这个测试应用程序时,我得到了类似的结果,这非常好,因为我可以从中找到一个xor掩码,以后可以与BitBlt一起使用

已删除死掉的Imageshack链接-屏幕截图

问题是,在Vista或启用Aero的Windows7上,窗口上不一定有区域,事实上在大多数情况下没有。有人能帮我想办法在这些平台上制作这样的面具吗

以下是我已经尝试过的一些方法

1。使用函数:这不起作用,因为它会返回Aero关闭时窗口的截图,并且此窗口与Aero打开时返回的窗口的形状不同

2使用获取完整大小的缩略图:这不起作用,因为它直接绘制到屏幕上,并且从我可以告诉您的情况来看,您无法直接从该api获取屏幕截图。是的,我可以打开一个粉红色背景的窗口,显示缩略图,截图,然后隐藏这个临时窗口,但这是一个可怕的用户体验和一个完整的黑客我宁愿没有我的名字

3。使用pinvoke或其他pinvoke变体:这不起作用,因为我不能假设我需要的信息窗口位于屏幕z顺序的顶部

现在,我能想到的最好的解决方案是在Windows7和Vista上使用特例Aero,通过对我绘制的一些图形路径进行硬编码来手动擦角,但这种解决方案会很糟糕,因为任何执行自定义蒙皮的应用程序都会打破这一点

你能想出另一个或更好的解决方案吗

如果你在这里,感谢你花时间阅读这篇文章,我感谢你能提供的任何帮助或指导

删除了一个可怕的想法,但在90年代会非常棒

您说使用DWMAPI只允许您直接捕获到屏幕上。。。你能创建一个屏幕外的窗口(比如说,X=-100000px,Y=-100000px)但可见(甚至可能隐藏?)并绘制屏幕截图吗?因为使用DWM时,每个窗口都有一个背景纹理,所以我认为即使目标不是直接出现在屏幕上,也可能会绘制得很好

另外,如果您想使用DirectX路线并访问窗口背后的实际DX纹理,我发现了一些可能有用的线索(尤其是第一个链接):


如果您正在寻找一个已完成的应用程序,则还有一个可以捕获半透明效果的应用程序,因此可以将图像保存为PNG格式,以便以后进行合成

编辑:

原始问题和注释表明,您希望在Windows Vista/7上生成一个区域,然后可以使用该区域遮罩捕获的图像的各个部分,就像在Windows XP和非Aero UI上所做的那样。使用区域并不能得到所需的结果,因为窗口轮廓不是作为区域计算的,而是作为具有可变透明度(RGBA)的图像计算的。该图像中的Alpha通道是您的遮罩,但它不像区域那样是一个开关遮罩,而是一个渐变遮罩,其值范围从像素完全包含到完全遮罩

尽管它使用未记录的API,但代码会捕获到RGBA缓冲区,然后您可以使用该缓冲区渲染或保存图像,阴影和其他半透明效果保持不变

DwmCapture.cs
中更改

BackBufferFormat = Format.X8R8G8B8

(X8->A8)

然后,您应该能够从捕获的缓冲区访问通常的RGB数据和透明度。然后可以将其保存为PNG或其他格式,并使用alpha通道进行合成

  • 使用Graphics.CopyFromScreen或其他pinvoke变体: 这不行,因为我不行 假设我需要一扇窗户 来自的信息位于 屏幕上的z顺序

  • 如果您知道需要从哪个窗口获取信息,可以将其置于最前面,调用Graphics.CopyFromScreen,然后重置其z索引吗?我从经验中知道,Aero在项目处于背景时会做一些奇怪的事情,以使其玻璃界面正常工作(部分渲染等)。这可能不太好;但是,这是一种特殊情况,仅在启用Aero时使用。

    您可以查看的源代码,如主页上所述,它可以捕获圆角,并具有Aero Glass透明效果,并将其保存到PNG文件中。它是用C#编写的。

    有趣且经过深思熟虑的问题,我希望它得到更多的关注。您正在使用
    GetWindowRgn()
    获取窗口的区域。如果改用
    GetWindowDC()
    (获取窗口的DC,包括标题栏),然后使用
    SelectObject()
    GetObject()
    以这种方式检索区域,会发生什么情况?有什么不同吗?还有一个
    GetClipRgn()
    ,它可能会返回不同的形状。我还没有尝试过这种方法,我将在本周末尝试一下。尝试过,但不幸的是,它不起作用。如上所述,当打开Aero时,窗口的形状不同。嘿,我查看了示例,不幸的是,这种方法有两个问题。。。1.不支持用于获取Direct3D曲面的API,因此我无法使用这些函数和2。(回到1),它们似乎在Windows7和Vista之间发生了变化。所以显示的样本实际上不起作用
    BackBufferFormat = Format.X8R8G8B8
    
    BackBufferFormat = Format.A8R8G8B8