制作窗口捕获的位图支持透明度

问题描述 投票:0回答:1

我有一个功能,它捕获指定窗口句柄的图像,然后将图像保存到png文件。我正在使用gdi32。

这样可以正常工作,但对于具有透明度的窗口(例如:典型的花式游戏启动器),透明区域将为绿色(或粉红色,具体取决于TernaryRasterOperations)。

这是捕获的功能:

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和TransparentBlt(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);

我也尝试使用文件流进行保存,但是所有这些方法都会导致将相同的绿色应用于透明区域。

c# gdi+ opacity bitblt
1个回答
0
投票

透明窗口不使用alpha通道,而是使用Regions通知操作系统顶级窗口的哪些区域被视为窗口的一部分。区域在像素级别是布尔值;换句话说,没有部分透明度。

我想你需要使用GetWindowRgn来获取区域数据。从那里你可以尝试调用PtInRegion来查看特定像素是否应该是透明的。如果这太慢,则可能需要将整个区域绘制到屏幕外位图,以便您可以抓取原始像素数据以便更快地访问。

© www.soinside.com 2019 - 2024. All rights reserved.