• [转帖]C#捕获网页为图像


    参考原文(英文) http://www.codeproject.com/cs/media/IECapture.asp
    环境:Visual Studio.NET 2003 语言:C#
    系统需求:Windows + iexplore

         该程序的目标很明确,就是捕获IE浏览器打开的网页存为图像,附加的需求,我们能自定义图像的保存质量(控制图像的大小)。当然我们还要考虑当有多个浏览器窗口打开的时候,我们是捕获所有窗口的图像。
         废话不多说,我们开始说说这个程序如何实现。

    第一步:引用标准DLL

         该程序需要SHDocVw.dll 和 MSHTML.dll的支持,所以在我们的工程中需要添加两个com组件,在添加引用的对话框中选择com的标签页,然后找到Microsoft Internet Controls". 和Microsoft HTML Object Library,添加进来。

    第二步:添加必要的名称空间      

    using   System.Text;
    using   System.Runtime.InteropServices;
    using   System.Diagnostics;
    using   System.IO;
    using   System.Drawing.Imaging;
    using   SHDocVw;
    using   mshtml;

    第三步:调用user32.dll的函数

    [DllImport( " user32.dll " , CharSet = CharSet.Auto)]
    public    static    extern   IntPtr FindWindowEx(IntPtr parent   /**/ /* HWND */ ,
       IntPtr next   /**/ /* HWND */ ,   string   sClassName, IntPtr sWindowTitle);

    [DllImport( " user32.dll " , ExactSpelling = true , CharSet = CharSet.Auto)]
    public    static    extern   IntPtr GetWindow(IntPtr hWnd,   int   uCmd);

    [DllImport( " user32.Dll " )]
    public    static    extern    void   GetClassName( int   h, StringBuilder s,   int   nMaxCount);

    [DllImport( " user32.dll " )]
    private    static    extern    bool   PrintWindow(IntPtr hwnd, IntPtr hdcBlt,   uint   nFlags);

    public    const    int   GW_CHILD   =    5 ;
    public    const    int   GW_HWNDNEXT   =    2 ;

    第四步:找到一个打开的浏览器进程,并分配一个Browser Document给它。

    SHDocVw.WebBrowser m_browser   =    null ;
    SHDocVw.ShellWindows shellWindows   =    new   SHDocVw.ShellWindowsClass();

       // Find first availble browser window.
       // Application can easily be modified to loop through and
       // capture all open windows.
        string   filename;
        foreach   (SHDocVw.WebBrowser ie   in   shellWindows)
         {
           filename   =   Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
            if   (filename.Equals( " iexplore " ))
             {
               m_browser   =   ie;
                break ;  
           }
       }
        if   (m_browser   ==    null )
         {   
           MessageBox.Show( " No Browser Open " );
            return ;
       }

        // Assign Browser Document
        mshtml.IHTMLDocument2 myDoc   =   (mshtml.IHTMLDocument2)m_browser.Document;

    第五步:获取屏幕和网页的高度和宽度

        // Set scrolling on.
       myDoc.body.setAttribute( " scroll " ,   " yes " ,   0 );

       // Get Browser Window Height
        int   heightsize   =   ( int )myDoc.body.getAttribute( " scrollHeight " ,   0 );
       int   widthsize   =   ( int )myDoc.body.getAttribute( " scrollWidth " ,   0 );

       // Get Screen Height
        int   screenHeight   =   ( int )myDoc.body.getAttribute( " clientHeight " ,   0 );
       int   screenWidth   =   ( int )myDoc.body.getAttribute( " clientWidth " ,   0 );

    第六步:捕获算法

            这里要说明的是,其实没有什么组件可以让我们直接把网页完全捕获过来,我们还是从基本的一页一页捕捉,然后组合整个图像的方法来完成的。
            其基本思想是这样的:首先捕获该网页的第一个片段,然后滚动条滑道下一页,继续捕获下一个片段,然后这个片段组合到一个目标位图中,就像缝合起来。这个过程会循环进行,直到最后一个片段捕获完毕,缝合到目标位图中去。
              当然我们还可能遇到这样一种情况,就是网页比屏幕要宽,这是我们的程序仍然是先捕获第一个片段,然后浏览器滚动条水平移动,捕获剩余的部分,然后缝接起来,然后再进行上述的步骤。
    //Get bitmap to hold screen fragment.
    Bitmap bm = new Bitmap(screenWidth, screenHeight,
         System.Drawing.Imaging.PixelFormat.Format16bppRgb555);

    //Create a target bitmap to draw into.
    Bitmap bm2 = new Bitmap(widthsize + URLExtraLeft, heightsize +
         URLExtraHeight - trimHeight,
              System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
    Graphics g2 = Graphics.FromImage(bm2);

    Graphics g = null;
    IntPtr hdc;
    Image screenfrag = null;
    int brwTop = 0;
    int brwLeft = 0;
    int myPage = 0;
    IntPtr myIntptr = (IntPtr)m_browser.HWND;

    //Get inner browser window.
    int hwndInt = myIntptr.ToInt32();
    IntPtr hwnd = myIntptr;
    hwnd = GetWindow(hwnd, GW_CHILD);
    StringBuilder sbc = new StringBuilder(256);

    //Get Browser "Document" Handle
    while (hwndInt != 0)
    {
          hwndInt = hwnd.ToInt32();
          GetClassName(hwndInt, sbc, 256);

          if(sbc.ToString().IndexOf("Shell DocObject View", 0) > -1)
          {
              hwnd = FindWindowEx(hwnd, IntPtr.Zero,
                  "Internet Explorer_Server", IntPtr.Zero);
              break;
          }                
          hwnd = GetWindow(hwnd, GW_HWNDNEXT);
       }

    //Get Screen Height (for bottom up screen drawing)
    while ((myPage * screenHeight) < heightsize)
    {
          myDoc.body.setAttribute("scrollTop", (screenHeight - 5) * myPage, 0);
          ++myPage;
    }

    //Rollback the page count by one
    --myPage;

    int myPageWidth = 0;
       while ((myPageWidth * screenWidth) < widthsize)
    {
          myDoc.body.setAttribute("scrollLeft", (screenWidth - 5) * myPageWidth, 0);
          brwLeft = (int)myDoc.body.getAttribute("scrollLeft", 0);
          for (int i = myPage; i >= 0; --i)
          {
              //Shoot visible window
              g = Graphics.FromImage(bm);
              hdc = g.GetHdc();
              myDoc.body.setAttribute("scrollTop", (screenHeight - 5) * i, 0);
              brwTop = (int)myDoc.body.getAttribute("scrollTop", 0);
              PrintWindow(hwnd, hdc, 0);
              g.ReleaseHdc(hdc);
              g.Flush();
              screenfrag = Image.FromHbitmap(bm.GetHbitmap());
              g2.DrawImage(screenfrag, brwLeft + URLExtraLeft, brwTop +
                 URLExtraHeight);
          }
          ++myPageWidth;
    }

  • 相关阅读:
    使用nginx在本地查看angular打包项目
    iso与安卓遇到的问题
    Spark 常用的读取数据api
    Spark DataFrame常用API
    spark 词频统计
    spark-shell和spark-sql
    Spark中 RDD、DF、DS的区别与联系
    SparkSQL连接Hive
    spark安装 centos7
    scala安装 centos7
  • 原文地址:https://www.cnblogs.com/love2wllw/p/1738773.html
Copyright © 2020-2023  润新知