保存网页为图片——滚动截取IE(WebBrowse)

时间:2022-07-04 00:37:58

对IE进行编程一直觉得是相当可怕的事情,里面的接口、函数、事件之多,解释之乱,需要了解的方方面面知识之博,让我仿佛看到了微软就是造物主,因为它已成功制造了这样的混沌,弄就了宇宙的初始状态……

近来做个项目,要截取网页,试了获取mht,开始倒是成功了,但不知装了什么软件后,就再也无法保存成mht了,查了一堆资料,修复了一轮,又可以部份保存成功,如此不稳定肯定不能应用,放弃!不得不赞的是,网文快捕的保存网页的插件的确是精品,成功率很高,不知在后面作者做了多少工作,可惜作者没有作为接口提供。于是决定还是截网页为图片,同时获取其中文字保存用于查询的方式,经过几日无数查找资料尝试,在终于崩溃之前,玉帝可怜我,终于让我成功,一直以来从网上众人文章中获益良多,赶快贴出来给不知多少像我这样可怜的人。

首先,声名使用到的文件:

uses ComObj,shDocvw,MSHtml,OleCtrls,jpeg,ActiveX;

然后声明用于获取IE WebBrowse实例的函数名:

TObjectFromLResult = function(LRESULT: lResult; const IID: TIID;WPARAM: wParam; out pObject): HRESULT; stdcall;

再来一个函数,获取窗口图像的,非常好用啊,就算窗口被挡着、隐藏都能获取到,善用可以做出惊人效果来的东东:

function PrintWindow(SourceWindow: hwnd; Destination: hdc; nFlags: cardinal): bool; stdcall; external 'user32.dll' name 'PrintWindow';

获取IE实例及截图核心来了!


//获取IE实例,wHandle为IE的句柄,这段代码网上抄来,向作者致谢!
//wHandle可通过WindowFromPoint(GetCursorPos(pt))获得,获取的办
//法网上一搜一大堆了。
function GetIEFromHWND(wHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
hInst: HWND;
lRes: Cardinal;
MSG: Integer;
pDoc: IHTMLDocument2;
ObjectFromLresult: TObjectFromLresult;
begin
hInst := LoadLibrary('Oleacc.dll');
@ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult');
if @ObjectFromLresult <> nil then
begin
try
MSG := RegisterWindowMessage('WM_HTML_GETOBJECT');
SendMessageTimeOut(WHandle, MSG, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes);
Result := ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc);
if Result = S_OK then
(pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp,
IWebbrowser2, IE);
finally
FreeLibrary(hInst);
pDoc := nil;
end;
end;
end; {指定IE窗口句柄,滚动获取整个网页图片
此函数执行完后能把IE原来滚动条位置复原,听起来这事很简单,爷找资料却是找到傻了云!如果网页有D3D这种东东的话,网上说的getAttribute('scrollTop', 0)什么的就用不了,混乱!混乱啊!
看了在下这文而受益的同学,不要忘了来感谢下啊,我也弄得很辛苦的。
}
procedure SaveWebPic(hIEHandle: Integer; webJpg: TJPEGImage);
var
rect: TRect;
webBmp: TBitMap;
i, j, webTop, webLeft, tLeft, tTop: integer;
ht, vt: array of Integer;
ie: IWebbrowser2;
iDoc: IHTMLDocument2;
vElement: IHTMLElement2;
procedure CaptureWeb(destBmp: TBitmap; destLeft, destTop, width, height: Integer);
var
temBmp: TBitmap;
begin
temBmp := TBitMap.Create();
temBmp.Height := height+2;
temBmp.Width := width+2;
PrintWindow(hIEHandle, temBmp.Canvas.Handle, 0);
BitBlt(destBmp.Canvas.Handle, destLeft, destTop, destLeft+width, destTop+height, temBmp.Canvas.Handle, 2, 2, SRCCOPY);
temBmp.Free;
end;
begin
if not Assigned(webJpg) then
Exit;
if GetIEFromHWND(hIEHandle, ie) <> S_OK then
Exit;
iDoc := ie.Document as IHTMLDocument2;
webBmp := TBitMap.Create();
webBmp.PixelFormat := pf24bit;
try
//temCanvas.Handle := GetDC(hIEHandle);
iDoc.body.setAttribute('scroll', 'yes', 0);
//保存原来滚动条位置
vElement := (iDoc as IHTMLDocument3).documentElement as IHTMLElement2;
if not Assigned(vElement) then
vElement := iDoc.Body as IHTMLElement2;
tTop := vElement.scrollTop;
tLeft := vElement.scrollLeft;
//获得网页的大小
webBmp.Height := vElement.scrollHeight;//iDoc.Body.getAttribute('scrollHeight', 0);
webBmp.Width := vElement.scrollWidth;//iDoc.Body.getAttribute('scrollwidth', 0);
//获得显示网页的窗口大小
// windows.GetClientRect(hIEHandle, rect);
// rect.Bottom := rect.Bottom - GetSystemMetrics(SM_CXHSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);
// rect.Right := rect.Right - GetSystemMetrics(SM_CXVSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);
rect.Right := vElement.clientWidth;
rect.Bottom := vElement.clientHeight;
//计算纵向和横向每次截取时,截取的高度、宽度
//网页的截取办法是去零传凑整,如窗口的高度是H,而网页的高度是WH,可先
//截取WH-H部份,剩下通过循环按H截取
SetLength(vt, webBmp.Height div rect.Bottom + 1);
SetLength(ht, webBmp.Width div rect.Right + 1);
vt[0] := webBmp.Height - (webBmp.Height div rect.Bottom) * rect.Bottom;
ht[0] := webBmp.Width - (webBmp.Width div rect.Right) * rect.Right;
for i:=1 to Length(vt)-1 do
vt[i] := rect.Bottom;
for i:=1 to Length(ht)-1 do
ht[i] := rect.Right; webLeft := 0;
for i:=0 to Length(ht)-1 do begin
webTop := 0;
iDoc.Get_ParentWindow.Scroll(webLeft, webTop);
for j:=0 to Length(vt)-1 do begin
CaptureWeb(webBmp, webLeft, webTop, ht[i], vt[j]);
webTop := webTop + vt[j];
iDoc.Get_ParentWindow.Scroll(webLeft, webTop);
end;
webLeft := webLeft + ht[i];
end;
webJpg.Assign(webBmp);
webJpg.SaveToFile('z:\demo.jpg');
finally
webBmp.Free;
SetLength(vt, 0);
SetLength(ht, 0);
iDoc.Get_ParentWindow.Scroll(tLeft, tTop);
end;
end;  
 
 http://www.cnblogs.com/IceAir/archive/2011/04/11/2012744.html

保存网页为图片——滚动截取IE(WebBrowse)的更多相关文章

  1. Android高级图片滚动控件,编写3D版的图片轮播器

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17482089 大家好,好久不见了,最近由于工作特别繁忙,已经有一个多月的时间没写博 ...

  2. 【精心推荐】12款很好用的 jQuery 图片滚动插件

    这里收集了12款很好用的 jQuery 图片滚动插件分享给大家.jQuery 作为最流行的 JavaScript 框架,使用简单灵活,同时还有许多优秀的插件可供使用.其中最令人印象深刻的应用之一就是各 ...

  3. javascript实现图片滚动

    闲来无事捣鼓了一个原来的js图片滚动 首先看看 静态页的结构: <body> <a href="javascript: le()">向左</a> ...

  4. 实例源码--Android图片滚动切换效果

    下载源码 技术要点:  1.图片滚动切换技术 2.详细的源码注释 ...... 详细介绍: 1.图片滚动切换技术 本套源码实现了类似于网站图片滚动推广效果,效果不错,很不错的参考源码 2.源码目录 运 ...

  5. 10款很好用的 jQuery 图片滚动插件

    jQuery 作为最流行的 JavaScript 框架,使用简单灵活,同时还有许多优秀的插件可供使用.其中最令人印象深刻的应用之一就是各种很酷的图片效果,它可以让的网站更具吸引力.这里收集了10款很好 ...

  6. 图片滚动js 实现图片无缝滚动

    在改章节中,我们主要介绍图片滚动的内容,自我感觉有个不错的建议和大家分享下 非常平滑的JS图片滚动特效代码,无缝循环,速度可自定义,鼠标悬停时停止.它的特点是JS和图片地址分离,这样做你就经易的从数据 ...

  7. 原生js实现tab选项卡里内嵌图片滚动特效代码

    <!DOCTYPE HTML><html lang="en-US"><head><meta charset="UTF-8&quo ...

  8. jquery图片滚动

    注:代码来自17sucai网,已去除部分冗余代码,只保留图片效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// ...

  9. Java图片工具类,完成图片的截取和任意缩放

    package com.common.util; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Renderin ...

随机推荐

  1. 高可用mysql之MHA源码剖析

    * MHA的整个故障(离线)切换过程 - 检测主库的状态,确认是否崩溃. - 确认服务崩溃,保存binlog,推送到主控机,并可以强制关闭主库避免脑裂. - 找出数据最新的从库(也就是read_mas ...

  2. php读取出字符串中的img标签中的图片路径

    php读取出字符串中的img标签中的图片路径 $pageContents = '字符串,带img标签'; $pageContents = str_replace('\"','"', ...

  3. Android屏蔽HOME键

    public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000; @Override protected void onCreate(Bund ...

  4. 关于JAVA应用中文字体显示小方框的问题解决

    最近碰到linux下jboss应用中中文字体显示为小方框: “在JRE 5以上的java环境中,java会自动加载$JAVA_HOME/jre/lib/fonts目录下的字体.链接或复制宋体或微软雅黑 ...

  5. JavaScript学习代码整理&lpar;一&rpar;

    /** * Created by wyl on 15-1-23. */ function displayDate() { document.getElementById("demo&quot ...

  6. 在C&num;中如何确定一个文件是不是文本文件,以及如何确定一个文件的类型

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:在C#中如何确定一个文件是不是文本文件,以及如何确定一个文件的类型.

  7. 用ajax写分页查询-----2017-05-17

    要写分页,首先你得清楚,一页你想显示多少条信息?如何计算总共显示的页数? 先说一下思路: (1)从数据库读取数据,以chenai表为例,读取所有留言信息.并能够实现输入发送者,可以查询该发送者的留言总 ...

  8. 关于jquery全选反选 批量删除的一点心得

    废话不多说直接上代码: 下面是jsp页面的html代码: <table id="contentTable" class=""> <thead& ...

  9. C&num;中多线程的并行处理

    System.Threading.Tasks,在该命名空间下Task是主类,表示一个类的异步的并发的操作,创建并行代码的时候不一定要直接使用Task类,在某些情况下可以直接使用Parallel静态类( ...

  10. hdu 5525 Product 数论算贡献

    Product Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Proble ...