简体   繁体   中英

How to take a screenshot of a Full Size window in C#

I am trying to create an application in C#.net that captures the screenshot of the current active window including the area that has to be scrolled using scroll bars.I found the following code to take screenshot. To be very clear I want the code to take screenshot of the active window including the area that is not displayed and is only revealed by using scroll bars.

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();
    }
}

You're making an assumption here that's not necessarily true: that there's something there already waiting in the unscrolled area. An application can build scroll bars for a certain height or width and not actually render anything to the surface until the user actual drags the scroll bar. The image you want to capture exists only in potential. This can be used to improve performance — think just-in-time loading, or reducing memory use. It's a fairly common technique, and so what you're asking for doesn't really make sense.

在不使用任何Win32 API调用的情况下捕获屏幕内容,只需在CodeProject上使用.NET 2.0。

If you're trying to get content that's offscreen, then WM_PRINT may work. BitBlt assuredly will not.

See:

You would need to redraw the whole window/form onto a graphics object. A (simple) example of how this can be done can be found in this CodeProject article . You'd need to implement support for all controls that you need in your project. Also, if you resize the window in the example application (obscure some controls) and make a test print, you'll see that the main form, which is just another control, is drawn over the other controls, which is no real problem but doesn't look very good - you could just remove support for drawing the main form if thats an issue.

Alternatively, if using or switching to WPF, you can print controls (including the main window) by using PrintDialog.PrintVisual().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM