我具有一个函数,该功能捕获指定窗口句柄的图像,然后将图像保存到PNG文件中。我正在使用GDI32。
这可以正常工作,但是对于具有透明度的窗口(示例:典型的花式游戏启动器),透明区域将为绿色(或粉红色,取决于ternaryrasteroferations)。
这是执行捕获的功能:
private static Image CaptureWindow(IntPtr handle) {
IntPtr hdc = GetWindowDC(handle);
RECT winRect = new RECT();
if (GetWindowRect(handle, out winRect)) {
Size winSize = new Size(winRect.Right - winRect.Left, winRect.Bottom - winRect.Top);
IntPtr hdcDest = CreateCompatibleDC(hdc);
IntPtr hBitmap = CreateCompatibleBitmap(hdc, winSize.Width, winSize.Height);
IntPtr hOld = SelectObject(hdcDest, hBitmap);
//if (TransparentBlt(hdcDest, 0, 0, winSize.Width, winSize.Height, hdc, 0, 0, winSize.Width, winSize.Height, ColorToUint(Color.Green))) {
if (BitBlt(hdcDest, 0, 0, winSize.Width, winSize.Height, hdc, 0, 0, TernaryRasterOperations.SRCCOPY)) {
SelectObject(hdcDest, hOld);
DeleteDC(hdcDest);
ReleaseDC(handle, hdc);
Image img = System.Drawing.Image.FromHbitmap(hBitmap);
DeleteObject(hBitmap);
return img;
}
}
return null;
}
我尝试了bitblt和透明blt(msimg32)。
保存图像时,我尝试了:
img.Save("file.png", ImageFormat.Png);
〜
img = img.Clone(new Rectangle(new Point(0, 0), img.Size), PixelFormat.Format32bppArgb);
img.Save("file.png", ImageFormat.Png);
〜
img.MakeTransparent(Color.Green);
img.Save("file.png", ImageFormat.Png);
我还尝试使用某个地方建议的文件流来保存,但是所有这些方法都将相同的绿色应用于透明区域。
透明窗口不使用alpha通道,而是使用区域通知OS,顶级窗口的哪个区域被认为是窗口的一部分。区域在像素水平上是布尔值;换句话说,没有部分透明度。
我认为您需要使用GetWindowRgn
获取区域数据。您可以尝试调用PtInRegion
,以查看特定像素是否应该透明。如果那太慢,则可能有必要将整个区域绘制到屏幕外位图上,以便您可以捕获原始像素数据以更快地访问。