+1 vote
1 view
in Devops and Agile by (17.9k points)

What is the best way to take a screenshot of a web page? At the moment I just start a selenium instance of firefox and using winapi bring it to the front and make a screenshot. I ask a similar question already.

There are two points:

  • Slowness.
  • If any window currently gets higher than our web browser's window, this window will imprint in our screenshot.

Is there any method to take screenshot more 'programming'?

Here is some code I use now:

class FirefoxDriverEx : FirefoxDriver

{

    public Process GetFirefoxProcess()

    {

        var fi = typeof(FirefoxBinary).GetField("process", BindingFlags.NonPublic | BindingFlags.Instance);

        return fi.GetValue(this.Binary) as Process;

    }

}

Here is the code illustrating the process of taking screenshot itself:

using (FirefoxDriverEx driver = new FirefoxDriverEx())

{

    driver.Navigate().GoToUrl(url);

    var process = driver.GetFirefoxProcess();

    if (process != null)

    {

        var screenCapture = new ScreenCapture();

        Win.SetForegroundWindow(process.MainWindowHandle.ToInt32());

    }

}

Right now, I'm thinking about some manager that will control a queue of windows to take the screenshots from.

Question edit#1:

I'm not looking for a solution to just get screenshot 'in memory' and return it back to HTTP stream. So anyways to save the screenshot and save it to file and then get it from there is very ambiguous for that purpose.

Question edit #2.

I forgot to mention. The needed screenshot should be made as it is seen by the user. So, the screenshot should have browser window and a site inside of web browser window's bounds. I can't find any way to change the mode of taking a screenshot in WebDriver of selenium. WebDriver just take a screenshot of a page without any browser window.   

1 Answer

0 votes
by (48.5k points)

If you're looking for a programmatic way to get a screenshot of the main window of a given process, here is a function that does the work:

public static Bitmap TakeScreenshot(Process process)

    {

        // may need a process Refresh before

        return TakeScreenshot(process.MainWindowHandle);

    }

    public static Bitmap TakeScreenshot(IntPtr handle)

    {

        RECT rc = new RECT();

        GetWindowRect(handle, ref rc);

        Bitmap bitmap = new Bitmap(rc.right - rc.left, rc.bottom - rc.top);

        using (Graphics graphics = Graphics.FromImage(bitmap))

        {

            PrintWindow(handle, graphics.GetHdc(), 0);

        }

        return bitmap;

    }

    [DllImport("user32.dll")]

    private static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);

    [DllImport("user32.dll")]

    private static extern bool PrintWindow(IntPtr hWnd, IntPtr hDC, int flags);

    [StructLayout(LayoutKind.Sequential)]

    private struct RECT

    {

        public int left;

        public int top;

        public int right;

        public int bottom;

    }

Unfortunately, on Aero-equipped OS (Vista/Win7/Win8) it will not capture the whole transparent border. The usual transparent border will be blacked instead. Maybe it's enough for what you're trying to accomplish.

...