Захват окна с помощью WPF - PullRequest
3 голосов
/ 15 ноября 2009

В Windows Presentation Foundation, если у меня есть HWND, как я могу захватить его окно как изображение, которое я могу манипулировать и отображать?

Ответы [ 2 ]

9 голосов
/ 15 ноября 2009

Вы можете:

  1. CreateBitmap() для создания hBitmap
  2. Звоните GetDC() на hWnd
  3. BitBlt() содержимое hBitmap
  4. ReleaseDC()
  5. Позвоните Imaging.CreateBitmapSourceFromHBitmap(), чтобы создать управляемый BitmapSource
  6. DeleteObject() на hBitmap
  7. Используйте BitmapSource по желанию

Шаги 1-4 и 6 используют Win32 API (точнее GDI), шаги 5 и 7 выполняются с использованием WPF

7 голосов
/ 21 января 2010

Хотя приведенный выше ответ хорош, это также сэкономило бы массу времени:

Использование раздела:

using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;

Код:

/// <summary>
/// Captures screenshot using WINAPI.
/// </summary>
static public class CaptureScreenshot
{
    /// <summary>
    /// Capture the screenshot.
    /// <param name="area">Area of screenshot.</param>
    /// <returns>Bitmap source that can be used e.g. as background.</returns>
    /// </summary>
    public static BitmapSource Capture(Rect area)
    {
        IntPtr screenDC = GetDC(IntPtr.Zero);
        IntPtr memDC = CreateCompatibleDC(screenDC);
        IntPtr hBitmap = CreateCompatibleBitmap(screenDC, (int)SystemParameters.VirtualScreenWidth, (int)SystemParameters.VirtualScreenHeight);
        SelectObject(memDC, hBitmap); // Select bitmap from compatible bitmap to memDC

        // TODO: BitBlt may fail horribly
        BitBlt(memDC, 0, 0, (int)area.Width, (int)area.Height, screenDC, (int)area.X, (int)area.Y, TernaryRasterOperations.SRCCOPY);
        BitmapSource bsource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

        DeleteObject(hBitmap);
        ReleaseDC(IntPtr.Zero, screenDC);
        ReleaseDC(IntPtr.Zero, memDC);
        return bsource;
    }

    #region WINAPI DLL Imports

    [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
    static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

    [DllImport("gdi32.dll")]
    private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

    [DllImport("gdi32.dll", SetLastError = true)]
    private static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [DllImport("gdi32.dll")]
    private static extern bool DeleteObject(IntPtr hObject);

    [DllImport("gdi32.dll")]
    private static extern IntPtr CreateBitmap(int nWidth, int nHeight, uint cPlanes, uint cBitsPerPel, IntPtr lpvBits);

    [DllImport("user32.dll")]
    private static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    private enum TernaryRasterOperations : uint
    {
        /// <summary>dest = source</summary>
        SRCCOPY = 0x00CC0020,
        /// <summary>dest = source OR dest</summary>
        SRCPAINT = 0x00EE0086,
        /// <summary>dest = source AND dest</summary>
        SRCAND = 0x008800C6,
        /// <summary>dest = source XOR dest</summary>
        SRCINVERT = 0x00660046,
        /// <summary>dest = source AND (NOT dest)</summary>
        SRCERASE = 0x00440328,
        /// <summary>dest = (NOT source)</summary>
        NOTSRCCOPY = 0x00330008,
        /// <summary>dest = (NOT src) AND (NOT dest)</summary>
        NOTSRCERASE = 0x001100A6,
        /// <summary>dest = (source AND pattern)</summary>
        MERGECOPY = 0x00C000CA,
        /// <summary>dest = (NOT source) OR dest</summary>
        MERGEPAINT = 0x00BB0226,
        /// <summary>dest = pattern</summary>
        PATCOPY = 0x00F00021,
        /// <summary>dest = DPSnoo</summary>
        PATPAINT = 0x00FB0A09,
        /// <summary>dest = pattern XOR dest</summary>
        PATINVERT = 0x005A0049,
        /// <summary>dest = (NOT dest)</summary>
        DSTINVERT = 0x00550009,
        /// <summary>dest = BLACK</summary>
        BLACKNESS = 0x00000042,
        /// <summary>dest = WHITE</summary>
        WHITENESS = 0x00FF0062
    }

    [DllImport("gdi32.dll")]
    private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);

    #endregion
}

Обратите внимание, что это снимок экрана с данной областью на экране, а не с окном. Это работает для моих целей, вам, вероятно, придется изменить его для своих:)

...