Как сделать скриншот полноразмерного окна в C # - PullRequest
2 голосов
/ 14 ноября 2010

Я пытаюсь создать приложение на C # .net, которое делает снимок экрана текущего активного окна, включая область, которую необходимо прокручивать с помощью полос прокрутки. Чтобы было очень ясно, я хочу, чтобы код делал снимок экрана активного окна, включая область, которая не отображается и отображается только с помощью полос прокрутки.

public class ScreenShot
{
    /// <summary>
    /// Captures the screenshot of the entire desktop
    /// </summary>
    /// <returns>Image object containing the screenshot of the desktop</returns>
    private Image CaptureDesktop()
    {
        return CaptureWindow(User32.GetDesktopWindow());
    }

    public Image CaptureAciveWindow()
    {
        return CaptureWindow(User32.GetForegroundWindow());
    }

    /// <summary>
    /// An Internal method, that captures the screenshot of any given Application window, given its Handle.
    /// </summary>
    /// <param name="handle">The handle of the window you want to Capture</param>
    /// <returns>An Image object containing the screenshot of the active application window</returns>
    private Image CaptureWindow(IntPtr handle)
    {
        // get te hDC of the target window
        IntPtr hdcSrc = User32.GetWindowDC(handle);
        // get the size
        User32.RECT windowRect = new User32.RECT();
        User32.GetWindowRect(handle, ref windowRect);
        int width = windowRect.right - windowRect.left;
        int height = windowRect.bottom - windowRect.top;
        // create a device context we can copy to
        IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
        // create a bitmap we can copy it to,
        // using GetDeviceCaps to get the width/height
        IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
        // select the bitmap object
        IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
        // bitblt over
        GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
        // restore selection
        GDI32.SelectObject(hdcDest, hOld);
        // clean up 
        GDI32.DeleteDC(hdcDest);
        User32.ReleaseDC(handle, hdcSrc);
        // get a .NET image object for it
        Image img = Image.FromHbitmap(hBitmap);
        // free up the Bitmap object
        GDI32.DeleteObject(hBitmap);

        return img;
    }

    /// <summary>
    /// Helper class containing Gdi32 API functions
    /// </summary>
    private class GDI32
    {
        public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter

        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
            int nWidth, int nHeight, IntPtr hObjectSource,
            int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
            int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    }

    /// <summary>
    /// Helper class containing User32 API functions
    /// </summary>
    private class User32
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        /// <summary>
        /// Gets the Handle for current active window
        /// </summary>
        /// <returns>Active windows Handle</returns>
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();
    }
}

Ответы [ 4 ]

4 голосов
/ 14 ноября 2010

Вы делаете здесь предположение, что это не обязательно верно: что там что-то уже ждет в области без прокрутки.Приложение может создавать полосы прокрутки для определенной высоты или ширины и фактически ничего не отображать на поверхности, пока пользователь не перетянет полосу прокрутки.Изображение, которое вы хотите захватить, существует только в потенциале.Это может быть использовано для повышения производительности - подумайте о своевременной загрузке или уменьшении использования памяти.Это довольно распространенная техника, и поэтому то, что вы просите, на самом деле не имеет смысла.

3 голосов
/ 14 ноября 2010

Захват содержимого экрана без использования вызовов Win32 API, просто с помощью .NET 2.0 на CodeProject .

1 голос
/ 23 июня 2011

Вам необходимо перерисовать все окно / форму на графический объект. (Простой) пример того, как это можно сделать, можно найти в этой статье CodeProject . Вам нужно будет реализовать поддержку всех элементов управления, которые вам нужны в вашем проекте. Кроме того, если вы измените размер окна в примере приложения (замаскируйте некоторые элементы управления) и сделаете тестовую распечатку, вы увидите, что основная форма, которая является просто еще одним элементом управления, рисуется поверх других элементов управления, что не является реальной проблемой, кроме выглядит не очень хорошо - вы можете просто удалить поддержку для рисования основной формы, если это проблема.

В качестве альтернативы, если вы используете или переключаетесь на WPF, вы можете распечатать элементы управления (включая главное окно) с помощью PrintDialog.PrintVisual ().

1 голос
/ 14 ноября 2010

Если вы пытаетесь получить контент, находящийся вне экрана, тогда WM_PRINT может работать. BitBlt наверняка не будет.

См .:

...