外部活动窗口的屏幕截图

时间:2014-12-08 17:16:07

标签: c# screenshot

我最近找到了一个代码来制作活动窗口的屏幕截图。它实际上工作但是图像有点太大,它在当前窗口的边界之外稍微有点。

这是我的程序截图: this is the screenshot taken with my program

这是使用alt + printscreen拍摄的屏幕截图: This is the screenshot taken with alt+printscreen

这是我的班级:

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

我只想让它截图显示活动窗口而不是窗外的一点点。我希望有人可以帮助我:)。

1 个答案:

答案 0 :(得分:0)

我遇到了你所描述症状的问题。在我的情况下,这是因为窗口在系统中注册为“前景”的时刻和实际完全显示在其他窗口前面的屏幕上的时刻之间的延迟。你可能会观察到同样的情况当您执行g.CopyFromScreen(...)时,您将获得屏幕区域中可能仍处于从前一个前景窗口转换到当前窗口的像素。 在第一个保存的图像中,您可以看到在我的图像捕获程序启动后150毫秒内制作的前景窗口(命令提示符)的屏幕截图:

Screenshot of "foreground" window in with 150 milliseconds delay

如您所见,它是先前前景窗口像素(Visual Studio)和新像素的混合。

完全更新屏幕需要150毫秒: Screenshot of fully updated foreground window (300 ms delay)

因此,屏幕截图的大小并不正确 - 这是新的前景窗口尚未“膨胀”到最终边界。 一个简单(丑陋)的解决方案是:在调用Thread.Sleep(...)之前插入g.CopyFromScreen(...),为系统提供足够的时间来完全替换屏幕上的像素。