参考原文(英文) http://www.codeproject.com/cs/media/IECapture.asp 
环境:Visual Studio.NET 2003 语言:C#
系统需求:Windows + iexplore                                                       附件:捕获网页为图像程序
捕获效果图:

捕获网页为图像_Windows


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

        废话不多说,我们开始说说这个程序如何实现。

第一步: 
         该程序需要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;
  }