zoukankan      html  css  js  c++  java
  • 保存网页为图片——滚动截取IE(WebBrowse)

    转自:http://www.cnblogs.com/IceAir/archive/2011/04/11/2012744.html

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

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

       首先,声名使用到的文件、用于获取IE WebBrowse实例的函数名、获取窗口图像的函数名:

    [delphi] view plain copy
     
     print?
    1. uses ComObj,shDocvw,MSHtml,OleCtrls,jpeg,ActiveX;  
    2.   
    3. TObjectFromLResult = function(LRESULT: lResult; const IID: TIID;WPARAM: wParam; out pObject): HRESULT; stdcall;  
    4.   
    5. //获取窗口图像的,非常好用啊,就算窗口被挡着、隐藏都能获取到  
    6. function PrintWindow(SourceWindow: hwnd; Destination: hdc; nFlags: cardinal): bool; stdcall; external 'user32.dll' name 'PrintWindow';  

           获取IE实例及截图核心代码:

    [delphi] view plain copy
     
     print?
    1. //获取IE实例,wHandle为IE的句柄,这段代码网上抄来,向作者致谢!  
    2. //wHandle可通过WindowFromPoint(GetCursorPos(pt))获得,获取的办法网上一搜一大堆了。  
    3. function GetIEFromHWND(wHandle: HWND; var IE: IWebbrowser2): HRESULT;  
    4. var  
    5.   hInst: HWND;  
    6.   lRes: Cardinal;  
    7.   MSG: Integer;  
    8.   pDoc: IHTMLDocument2;  
    9.   ObjectFromLresult: TObjectFromLresult;  
    10. begin  
    11.   hInst := LoadLibrary('Oleacc.dll');  
    12.   @ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult');  
    13.   if @ObjectFromLresult <> nil then  
    14.   begin  
    15.     try  
    16.       MSG := RegisterWindowMessage('WM_HTML_GETOBJECT');  
    17.       SendMessageTimeOut(WHandle, MSG, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes);  
    18.       Result := ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc);  
    19.       if Result = S_OK then  
    20.         (pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp,  
    21.           IWebbrowser2, IE);  
    22.     finally  
    23.       FreeLibrary(hInst);  
    24.       pDoc := nil;  
    25.     end;  
    26.   end;  
    27. end;  
    28.   
    29.   
    30. {指定IE窗口句柄,滚动获取整个网页图片 
    31. 此函数执行完后能把IE原来滚动条位置复原,听起来这事很简单,找资料却是找到傻了云!如果网页有D3D这种东东的话,网上说的getAttribute('scrollTop', 0)什么的就用不了,弄得很辛苦的。 
    32. }  
    33. procedure SaveWebPic(hIEHandle: Integer; webJpg: TJPEGImage);  
    34. var  
    35.   rect: TRect;  
    36.   webBmp: TBitMap;  
    37.   i, j, webTop, webLeft, tLeft, tTop: integer;  
    38.   ht, vt: array of Integer;  
    39.   ie: IWebbrowser2;  
    40.   iDoc: IHTMLDocument2;  
    41.   vElement: IHTMLElement2;  
    42.   procedure CaptureWeb(destBmp: TBitmap; destLeft, destTop, width, height: Integer);  
    43.   var  
    44.     temBmp: TBitmap;  
    45.   begin  
    46.     temBmp := TBitMap.Create();  
    47.     temBmp.Height := height+2;  
    48.     temBmp.Width := width+2;  
    49.     PrintWindow(hIEHandle, temBmp.Canvas.Handle, 0);  
    50.     BitBlt(destBmp.Canvas.Handle, destLeft, destTop, destLeft+width, destTop+height, temBmp.Canvas.Handle, 2, 2, SRCCOPY);  
    51.     temBmp.Free;  
    52.   end;  
    53. begin  
    54.   if not Assigned(webJpg) then  
    55.     Exit;  
    56.   if GetIEFromHWND(hIEHandle, ie) <> S_OK then  
    57.     Exit;  
    58.   iDoc := ie.Document as IHTMLDocument2;  
    59.   webBmp := TBitMap.Create();  
    60.   webBmp.PixelFormat := pf24bit;  
    61.   try  
    62.     //temCanvas.Handle := GetDC(hIEHandle);  
    63.     iDoc.body.setAttribute('scroll', 'yes', 0);  
    64.     //保存原来滚动条位置  
    65.     vElement := (iDoc as IHTMLDocument3).documentElement as IHTMLElement2;  
    66.     if not Assigned(vElement) then  
    67.       vElement := iDoc.Body as IHTMLElement2;  
    68.     tTop := vElement.scrollTop;  
    69.     tLeft := vElement.scrollLeft;  
    70.     //获得网页的大小  
    71.     webBmp.Height := vElement.scrollHeight;//iDoc.Body.getAttribute('scrollHeight', 0);  
    72.     webBmp.Width := vElement.scrollWidth;//iDoc.Body.getAttribute('scrollwidth', 0);  
    73.     //获得显示网页的窗口大小  
    74. //    windows.GetClientRect(hIEHandle, rect);  
    75. //    rect.Bottom := rect.Bottom - GetSystemMetrics(SM_CXHSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);  
    76. //    rect.Right := rect.Right - GetSystemMetrics(SM_CXVSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);  
    77.      rect.Right := vElement.clientWidth;  
    78.      rect.Bottom := vElement.clientHeight;  
    79.     //计算纵向和横向每次截取时,截取的高度、宽度  
    80.     //网页的截取办法是去零传凑整,如窗口的高度是H,而网页的高度是WH,可先  
    81.     //截取WH-H部份,剩下通过循环按H截取  
    82.     SetLength(vt, webBmp.Height div rect.Bottom + 1);  
    83.     SetLength(ht, webBmp.Width div rect.Right + 1);  
    84.     vt[0] := webBmp.Height - (webBmp.Height div rect.Bottom) * rect.Bottom;  
    85.     ht[0] := webBmp.Width - (webBmp.Width div rect.Right) * rect.Right;  
    86.     for i:=to Length(vt)-do  
    87.       vt[i] := rect.Bottom;  
    88.     for i:=to Length(ht)-do  
    89.       ht[i] := rect.Right;  
    90.         
    91.     webLeft := 0;  
    92.     for i:=to Length(ht)-do begin  
    93.       webTop := 0;                     
    94.       iDoc.Get_ParentWindow.Scroll(webLeft, webTop);  
    95.       for j:=to Length(vt)-do begin  
    96.         CaptureWeb(webBmp, webLeft, webTop, ht[i], vt[j]);  
    97.         webTop := webTop + vt[j];  
    98.         iDoc.Get_ParentWindow.Scroll(webLeft, webTop);  
    99.       end;  
    100.       webLeft := webLeft + ht[i];  
    101.     end;  
    102.     webJpg.Assign(webBmp);  
    103.     webJpg.SaveToFile('z:demo.jpg');  
    104.   finally  
    105.     webBmp.Free;  
    106.     SetLength(vt, 0);  
    107.     SetLength(ht, 0);  
    108.     iDoc.Get_ParentWindow.Scroll(tLeft, tTop);  
    109.   end;  
    110. end;  

    http://blog.csdn.net/tht2009/article/details/39736839

  • 相关阅读:
    CentOS 6.4 利用 Awstats 7.2 分析 Nginx 日志
    CentOS 6.4 x64 postfix + dovecot + 虚拟用户认证
    配置日志logwarch 每天发送到邮箱
    CentOSx64 安装 Gearmand 和 Gearman php扩展
    Redis之基本介绍
    Synchronized锁的基本介绍
    Lock的基本介绍
    java之threadlocal的使用
    Java之事务的基本应用
    linux之cp和scp的使用
  • 原文地址:https://www.cnblogs.com/findumars/p/5185163.html
Copyright © 2011-2022 走看看