Как вы делаете снимок экрана сайта через .Net код? - PullRequest
13 голосов
/ 17 марта 2009

Можно ли сделать снимок экрана с любым URL-адресом, используя код .Net?

Какой самый простой способ сделать это?

Ответы [ 4 ]

5 голосов
/ 17 марта 2009

Просто наткнулся на это: http://pietschsoft.com/post/2008/07/C-Generate-WebPage-Thumbmail-Screenshot-Image.aspx

Может быть, вы могли бы что-то использовать?

3 голосов
/ 17 марта 2009

Я бы предложил для этого использовать сторонний подход, а не делать это самостоятельно. Однако, если вы настаиваете, то жестким способом будет использовать System.Diagnostics.Process для запуска браузера, а затем GetDesktopImage для получения снимка экрана.

Я уверен, что есть более простой способ, но это выглядит так:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public class PlatformInvokeGDI32
{
    public  const int SRCCOPY = 13369376;

    [DllImport("gdi32.dll",EntryPoint="DeleteDC")]
    public static extern IntPtr DeleteDC(IntPtr hDc);

    [DllImport("gdi32.dll",EntryPoint="DeleteObject")]
    public static extern IntPtr DeleteObject(IntPtr hDc);

    [DllImport("gdi32.dll",EntryPoint="BitBlt")]
    public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp);

    [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")]
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc,int nWidth, int nHeight);

    [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")]
    public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [DllImport ("gdi32.dll",EntryPoint="SelectObject")]
    public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp);
}

public class PlatformInvokeUSER32
{
    public const int SM_CXSCREEN = 0;
    public const int SM_CYSCREEN = 1;

    [DllImport("user32.dll", EntryPoint="GetDesktopWindow")]
    public static extern IntPtr GetDesktopWindow();

    [DllImport("user32.dll",EntryPoint="GetDC")]
    public static extern IntPtr GetDC(IntPtr ptr);

    [DllImport("user32.dll",EntryPoint="GetSystemMetrics")]
    public static extern int GetSystemMetrics(int abc);

    [DllImport("user32.dll",EntryPoint="GetWindowDC")]
    public static extern IntPtr GetWindowDC(Int32 ptr);

    [DllImport("user32.dll",EntryPoint="ReleaseDC")]
    public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc);
}

public class CaptureScreen
{
    public static Bitmap GetDesktopImage()
    {
        //In size variable we shall keep the size of the screen.
        SIZE size;

        //Variable to keep the handle to bitmap.
        IntPtr hBitmap;

        //Here we get the handle to the desktop device context.
        IntPtr  hDC = PlatformInvokeUSER32.GetDC(PlatformInvokeUSER32.GetDesktopWindow());

        //Here we make a compatible device context in memory for screen device context.
        IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC);

        //We pass SM_CXSCREEN constant to GetSystemMetrics to get the
        //X coordinates of the screen.
        size.cx = PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CXSCREEN);

        //We pass SM_CYSCREEN constant to GetSystemMetrics to get the Y coordinates of the screen.
        size.cy = PlatformInvokeUSER32.GetSystemMetrics (PlatformInvokeUSER32.SM_CYSCREEN);

        //We create a compatible bitmap of the screen size and using the screen device context.
        hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hDC, size.cx, size.cy);

        //As hBitmap is IntPtr, we cannot check it against null.
        //For this purpose, IntPtr.Zero is used.
        if(hBitmap != IntPtr.Zero)
        {
            //Here we select the compatible bitmap in the memeory device
            //context and keep the refrence to the old bitmap.
            IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject(hMemDC, hBitmap);

            //We copy the Bitmap to the memory device context.
            PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, PlatformInvokeGDI32.SRCCOPY);

            //We select the old bitmap back to the memory device context.
            PlatformInvokeGDI32.SelectObject(hMemDC, hOld);

            //We delete the memory device context.
            PlatformInvokeGDI32.DeleteDC(hMemDC);

            //We release the screen device context.
            PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32.GetDesktopWindow(), hDC);

            //Image is created by Image bitmap handle and stored in local variable.
            Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap);

            //Release the memory to avoid memory leaks.
            PlatformInvokeGDI32.DeleteObject(hBitmap);

            //This statement runs the garbage collector manually.
            GC.Collect();

            //Return the bitmap
            return bmp;
        }

        //If hBitmap is null, retun null.
        return null;
    }
}

//This structure shall be used to keep the size of the screen.
public struct SIZE
{
  public int cx;
  public int cy;
}
2 голосов
/ 28 ноября 2012

Я искал повсюду, чтобы найти решение этой проблемы, и проблема с использованием WebBrowser и других предложений заключается в том, что вам необходим большой доступ к этой коробке.

На сегодняшний день это лучший сторонний инструмент, который мне удалось найти:

http://www.websitesscreenshot.com/

Их SEO ужасен, но я считаю, что нашел их на форуме или даже в стеке ... У меня есть лицензия, и вы получаете только одну DLL, на которую можете ссылаться. Передача лицензии конструктору удаляет их водяной знак.

После быстрого ознакомления с ILSpy я полагаю, что он интерпретирует HTML и выдает изображение для вашего удобства просмотра.

Использование

Сохранение URL

WebsitesScreenshot.WebsitesScreenshot  _Obj;
_Obj = new WebsitesScreenshot.WebsitesScreenshot ();
WebsitesScreenshot.WebsitesScreenshot.Result _Result;
_Result = _Obj.CaptureWebpage("http://www.google.com");
if (_Result == WebsitesScreenshot.WebsitesScreenshot.Result.Captured)
{
    _Obj.ImageFormat = WebsitesScreenshot.
        WebsitesScreenshot.ImageFormats.PNG;
    _Obj.SaveImage ("c:\\google.png");
}            
_Obj.Dispose();

Сохранение необработанной строки HTML

WebsitesScreenshot.WebsitesScreenshot _Obj;
_Obj=new WebsitesScreenshot.WebsitesScreenshot();
WebsitesScreenshot.WebsitesScreenshot.Result _Result;
_Result = _Obj.CaptureHTML(
"<html><body><h1> Hello world </h1></body></html>");
if (_Result == WebsitesScreenshot.WebsitesScreenshot.Result.Captured)
{
    _Obj.ImageFormat = WebsitesScreenshot.
        WebsitesScreenshot.ImageFormats.GIF;
    _Obj.SaveImage("c:\\test.gif");
}
_Obj.Dispose();

Вы можете найти больше на их странице использования. Найдено здесь:

http://www.websitesscreenshot.com/Usage.html

Надеюсь, это поможет!

Ура !!

2 голосов
/ 17 марта 2009

Есть несколько сторонних компонентов, которые делают это. По-видимому, это не тривиально, поскольку такие вещи, как Flash и другие вещи, например, не так легко запоминаются.

Я использовал HTMLSnapshot в прошлом и был доволен этим (это не бесплатно, но довольно дешево).

От всей души предлагаю вам не тратить слишком много времени на реализацию этого самостоятельно, потому что вы непременно должны будете переделать множество конечных случаев, которые уже обрабатываются этими сторонними решениями.

...