Создание растрового изображения захвата окна поддерживает прозрачность - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть функция, которая захватывает изображение указанного дескриптора окна, а затем сохраняет изображение в файл 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);

Я также пытался сохранить, используя файловый поток, как это было предложено где-то, но все эти методы приводят к тому же зеленому, применяемому к прозрачным областям.

1 Ответ

0 голосов
/ 28 февраля 2019

Прозрачные окна не используют альфа-канал, вместо этого они используют регионы для информирования ОС, какие области окна верхнего уровня считаются частью окна.Регионы логические на уровне пикселей;другими словами, нет частичной прозрачности.

Я думаю, вам нужно будет использовать GetWindowRgn для получения данных региона.Оттуда вы можете попробовать позвонить PtInRegion, чтобы увидеть, должен ли определенный пиксель быть прозрачным или нет.Если это слишком медленно, то может потребоваться нарисовать всю область за пределами экрана, чтобы вы могли получить необработанные данные пикселей для более быстрого доступа.

...