Захват скрытого окна в Vista

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

Итак, есть ли способ сделать снимок экрана, которое затемнено или частично за пределами экрана, путем прямого чтения этих буферов? Vista делает это, когда вы нажимаете Alt-Tab или наводите указатель мыши на панель задач.

Я делаю это в Delphi, но кода на любом языке будет достаточно.


person Mike Sutton    schedule 12.04.2009    source источник


Ответы (6)


Я считаю, что этих буферов не существует, когда эти окна находятся за пределами экрана. Или существуют только частично, когда частично за кадром.

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

person Nick Whaley    schedule 12.04.2009
comment
Буферы определенно есть и обновляются. Запустите воспроизведение видео, закройте его другим окном, наведите указатель мыши на панель инструментов, и вы получите эскиз воспроизводимого видео. - person Mike Sutton; 12.04.2009
comment
Ага, когда окно закрыто, но не когда оно свернуто. Я пробовал это раньше с проигрывателем Windows Media. - person U62; 12.04.2009
comment
Кроме того, по-видимому, начиная с Windows 7, приложения могут обновлять свои эскизы по желанию, не полагаясь на WM_PAINT (который не запускается для свернутых окон в качестве ограничения GDI). Windows Media Player 12 использует это для продолжения воспроизведения видео даже в свернутом виде. - person Joey; 12.04.2009
comment
К сожалению, это правильно. Даже написание собственного видеодвигателя не позволит вам захватить содержимое окна. - person Joshua; 13.04.2009

Вот код, который я написал давным-давно на C # для приложения захвата экрана. Он использует Win32-функцию GetWindowRect, чтобы получить границы окна, которое вы хотите захватить, создать растровое изображение с этим размером, а затем использовать Win32-функцию PrintWindow, чтобы попросить окно распечатать себя на это растровое изображение:

RECT lRectangle = new RECT();
if (!GetWindowRect(lWindow.HWnd, ref lRectangle))
{
    MessageBox.Show(this, "An error occured while measuring the selected window.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
    return;
}

fCapturedImage = new Bitmap(lRectangle.Right - lRectangle.Left, lRectangle.Bottom - lRectangle.Top, PixelFormat.Format32bppArgb);
using (Graphics lGraphics = Graphics.FromImage(fCapturedImage))
{
    HDC lHdc = lGraphics.GetHdc();
    PrintWindow(lWindow.HWnd, lHdc, 0);
    lGraphics.ReleaseHdc(lHdc);
}
person Tommy Carlier    schedule 12.04.2009

Что-нибудь полезное в этой теме ?: http://www.eggheadcafe.com/conversation.aspx?messageid=31543575&threadid=31543575

person dan-gph    schedule 13.04.2009

Считали ли вы подключением сообщения wm_paint? автор книги «Программирование графики Windows: Win32 GDI и DirectDraw» Фэн Юань сделал образец dll на этот счет. Я думаю, что таким образом можно также захватывать окна DirectXed (которые имеют буферный экран в любое время). пожалуйста, обратитесь к http://www.fengyuan.com/article/wmprint.html. Вы можете найти рабочие примеры delphi через Google. также проверьте expterts-exchange.com

person avar    schedule 14.04.2009

Я думаю, что в новом DWM APi (Desktop Windows Manager) может быть что-то, что позволит вам писать и устанавливать собственные диспетчеры рабочего стола с доступом к тем же эскизам, которые вы видите во Flip3d и других представлениях.

person Marco Cantù    schedule 15.04.2009

Сделайте это (C #)

    public static Bitmap PrintWindow(IntPtr hwnd)
    {
        RECT rc;
        WinUserApi.GetWindowRect(hwnd, out rc);

        Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
        Graphics gfxBmp = Graphics.FromImage(bmp);
        IntPtr hdcBitmap = gfxBmp.GetHdc();
        bool succeeded = WinUserApi.PrintWindow(hwnd, hdcBitmap, 0);
        gfxBmp.ReleaseHdc(hdcBitmap);
        if (!succeeded)
        {
            gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
        }
        IntPtr hRgn = WinGdiApi.CreateRectRgn(0, 0, 0, 0);
        WinUserApi.GetWindowRgn(hwnd, hRgn);
        Region region = Region.FromHrgn(hRgn);
        if (!region.IsEmpty(gfxBmp))
        {
            gfxBmp.ExcludeClip(region);
            gfxBmp.Clear(Color.Transparent);
        }
        gfxBmp.Dispose();
        return bmp;
    }
person Maurice Flanagan    schedule 07.05.2009