【问题标题】:How do you take a Screenshot of a website via .Net code?您如何通过 .Net 代码截取网站截图?
【发布时间】:2009-03-17 11:29:53
【问题描述】:

是否可以使用 .Net 代码截取任何给定 URL 的屏幕截图?

最简单的方法是什么?

【问题讨论】:

  • 使用哪个渲染引擎?毕竟不同的渲染引擎会产生不同的结果
  • webkit 似乎是最符合标准的
  • 哇。没想到这么容易:)

标签: .net web screenshot


【解决方案1】:

【讨论】:

    【解决方案2】:

    我建议为此使用第三方方法,而不是自己做。不过,如果你坚持,那么强硬的方法是使用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;
    }
    

    【讨论】:

      【解决方案3】:

      有几个 3rd 方组件可以做到这一点。显然这不是微不足道的,因为 Flash 之类的东西并不容易捕捉,例如。

      我过去使用过HTMLSnapshot,对它很满意(它不是免费的,但很便宜)。

      我衷心建议您不要浪费太多时间自行实施,因为您最终必然会重做这些 3rd 方解决方案已经处理的许多最终案例。

      【讨论】:

      • 我想知道是否有人建议拉里佩奇和谢尔盖布林相同:P
      【解决方案4】:

      我进行了广泛搜索以找到解决此问题的方法,而使用 WebBrowser 和其他建议的问题是您需要大量访问该框。

      迄今为止,这是我能找到的最好的第三方工具:

      http://www.websitesscreenshot.com/

      他们的 SEO 很糟糕,但我相信我是在论坛甚至 Stack 上找到他们的……我确实拥有许可证,而你得到的只是一个可供参考的 DLL。将许可证传递给构造函数会删除它们的水印。

      在快速浏览 ILSpy 之后,我相信它的作用是解释 HTML 并转储图像以供您查看。

      用法

      保存网址

      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

      希望这会有所帮助!

      干杯!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-14
        • 1970-01-01
        • 2011-10-25
        • 1970-01-01
        • 2010-11-14
        相关资源
        最近更新 更多