参考原文(英文) 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;
}