保存網頁爲圖片——滾動截取IE(WebBrowse)

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

   對IE進行編程一直覺得是相當可怕的事情,裏面的接口、函數、事件之多,解釋之亂,需要了解的方方面面知識之博,讓我彷彿看到了微軟就是造物主,因爲它已成功製造了這樣的混沌,弄就了宇宙的初始狀態……

   近來做個項目,要截取網頁,試了獲取mht,開始倒是成功了,但不知裝了什麼軟件後,就再也無法保存成mht了,查了一堆資料,修復了一輪,又可以部份保存成功,如此不穩定肯定不能應用,放棄!不得不讚的是,網文快捕的保存網頁的插件的確是精品,成功率很高,不知在後面作者做了多少工作,可惜作者沒有作爲接口提供。於是決定還是截網頁爲圖片,同時獲取其中文字保存用於查詢的方式,經過幾日無數查找資料嘗試,在終於崩潰之前,玉帝可憐我,終於讓我成功,一直以來從網上衆人文章中獲益良多,趕快貼出來給不知多少像我這樣可憐的人。

   首先,聲名使用到的文件、用於獲取IE WebBrowse實例的函數名、獲取窗口圖像的函數名:

 

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

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;

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章