Screenshot of active window out of bounds

I recently found some code to take a screenshot of the active window. It does work, however the image is a little too big, it goes a little beyond the current window.

This is a screenshot taken with my program: this is the screenshot taken with my program

This is a screenshot taken with alt + printscreen: This is the screenshot taken with alt + printscreen

This is my class:

public static class Screenshotter
{
    [DllImport("user32.dll")]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

    [DllImport("user32.dll")]
    private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);

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

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;        // x position of upper-left corner  
        public int Top;         // y position of upper-left corner  
        public int Right;       // x position of lower-right corner  
        public int Bottom;      // y position of lower-right corner  
    }

    public static void MakeScreenshot()
    {
        var foregroundWindowsHandle = GetForegroundWindow();
        var rect = new RECT();

        GetWindowRect(foregroundWindowsHandle, out rect);

        Rectangle bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);

        Bitmap bmp = new Bitmap(bounds.Width, bounds.Height);

        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
        }

        bmp.Save("test.png", ImageFormat.Png);
    }
}

      

I just want the screenshots to be the active window, not a little outside the window. I hope someone can help me :)

+3


source to share


1 answer


I am having a problem with the symptoms you described. In my case, this was due to the delay between the moments when the window was registered with the system as "foreground" and when it was actually completely displayed on the screen in front of other windows. You are probably seeing the same thing. When you execute g.CopyFromScreen(...)

, you get pixels from the screen area, which can still be translated from the previous foreground window to the current one.
In the first saved image, you can see a screenshot of the foreground (command line) taken 150 milliseconds after starting the image capture program:

Screenshot of "foreground" window in with 150 milliseconds delay

As you can see, this is a mixture of the previous pixels of the foreground window (Visual Studio) and the new one.



It took another 150ms to fully refresh the screen: Screenshot of fully updated foreground window (300 ms delay)

So, this is not your screenshot at the wrong size - this new foreground window has not yet "inflated" to its final bounds. Simple (and ugly) solution: insert Thread.Sleep(...)

before your call g.CopyFromScreen(...)

to give the system enough time to completely replace the pixels on the screen.

0


source







All Articles