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 a 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 :)
source to share
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:
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:
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.
source to share