• 滚动截取IE(WebBrowse)中的网页为图片


        对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;
  • 相关阅读:
    作业17
    模块
    Find the Lost Sock (异或算法)
    CD(二分)
    数字流输入
    最大连续子序列(dp)
    STL学习----lower_bound和upper_bound算法
    输入挂(减少时间)
    暴力之全排列
    【C++】判断元素是否在vector中,对vector去重,两个vector求交集、并集
  • 原文地址:https://www.cnblogs.com/IceAir/p/2012744.html
Copyright © 2020-2023  润新知