如何将 WebBrowser 渲染到设备上下文?

2023-11-24

我想渲染一个网页(即TWebBrowser) 到设备上下文。我想使用 Internet Explorer 的布局引擎将内容呈现到设备上下文(即图元文件、pdf 图元文件)。


从 Internet Explorer 9 开始IHTMLElementRender界面不再支持的:

IHTMLElementRender 接口

使用此接口将元素的内容绘制到指定的设备上下文(通常是打印机)。

Members
The IHTML元素渲染接口继承自IUnknown接口但没有额外的成员。

以至于他们不再提及绘制到DC方法甚至存在:

IHTMLElementRender::DrawToDC 方法

已弃用。将元素的内容绘制到指定的设备上下文。

Syntax

HRESULT DrawToDC(
     HDC hDC
);

参数

  • hDC
    [在]安HDC指定要绘制的设备,通常是打印机。

返回值

如果成功则返回 S_OK,否则返回错误值。

Remarks

从 Windows Internet Explorer 9 开始,此方法已被弃用,不应使用。

对于某些打印机,运行IHTMLElementRender::DrawToDC可能会导致问题。您可以确保IHTMLElementRender::DrawToDC通过运行可在所有打印机上正常工作IHTMLElementRender::SetDocumentPrinter首先方法,然后将修改后的设备上下文传递给IHTMLElementRender::DrawToDC.

Note:我引用了所有文档,以便当 Microsoft 最终从 MSDN 中完全删除它时仍然可以找到它。连同接口声明:

IHTMLElementRender = interface(IUnknown)
   ['{3050F669-98B5-11CF-BB82-00AA00BDCE0B}']
   function DrawToDC(hdc: HDC): HResult; stdcall;
   function SetDocumentPrinter(const bstrPrinterName: WideString; hdc: HDC): HResult; stdcall;
end;

Use the IViewObject界面

我尝试转换为使用IViewObject (e.g. 如何在不使用网络浏览器的情况下渲染 HTML 元素?):

procedure RenderWebBrowserToMetafile(Browser: TWebBrowser; Metafilename: string);
var
    view: IViewObject;
    m: TMetafile;
    mc: TMetafileCanvas;
    w, h: Integer;
    r: TRect;
    dpix: Integer;
    dpiy: Integer;
    dc: HDC;
begin
    w := WebBrowserScrollWidth(Browser);
    h := WebBrowserScrollHeightStrict(Browser);

    //96dpi screen to 300dpi metafile (destined for printer)
    dc := GetDC(0);
    try
        dpix := GetDeviceCaps(GetDC(0), LOGPIXELSX);
        dpiy := GetDeviceCaps(GetDC(0), LOGPIXELSY);
    finally
        ReleaseDC(0, dc);
    end;
    w := MulDiv(w, 300, dpix);
    h := MulDiv(h, 300, dpiy);

    view := Browser.Document as IViewObject;

    m := TMetafile.Create;
    try
        m.Width := w;
        m.Height := h;
        r := Rect(0, 0, w, h);

        mc := TMetafileCanvas.Create(m, 0);
        try
            view.Draw(
                    DVASPECT_CONTENT, //draw aspect
                    1, //index
                    nil, //pAspectInfo
                    nil, //pDVTargetDevice
                    0, //Target Device Context
                    mc.handle, //hdcDraw
                    @r, //target Bounds
                    @w, //window bounds (for metafiles)
                    nil, //continue function
                    0); //continue value
        finally
            mc.Free;
        end;
        m.SaveToFile(Metafilename);
    finally
        m.Free;
    end;
end;

这段代码的问题是它只渲染visible浏览器区域(即没有滚动内容):

我需要渲染entire网页(例如用于打印)。

我尝试改变绘制方面 from DVASPECT_CONTENT (as 这个例子确实),到DVASPECT_DOCPRINT:

DVASPECT_DOCPRINT
在屏幕上提供对象的表示,就像使用“文件”菜单中的“打印”命令将其打印到打印机一样。所描述的数据可以表示页面序列。

结果相同;不渲染页面,只渲染可见部分:

如何让 IE9 渲染引擎进行渲染?


我也尝试使用不同的indexes随着DVASPECT_DOCPRINT。虽然IViewObject没有记录,也许这就是你打印不同的方式"pages":

view.Draw(DVASPECT_DOCPRINT, 1, ...);
view.Draw(DVASPECT_DOCPRINT, 2, ...);
view.Draw(DVASPECT_DOCPRINT, 3, ...);
...
view.Draw(DVASPECT_DOCPRINT, n, ...);

但 Web 浏览器并不关心索引是什么;它关心的是索引是什么。只渲染当前的View(我认为使用时这是有意义的IViewObject).

如何将浏览器渲染到设备上下文?

Note:问题标记为delphi,但是这个问题没有任何内容delphi具体的。


Update:我还尝试了其他组合aspect and index:

view.Draw(DVASPECT_CONTENT, -1, ...);
view.Draw(DVASPECT_DOCPRINT, -1, ...);
view.Draw(DVASPECT_CONTENT, 0, ...);
view.Draw(DVASPECT_DOCPRINT, 0, ...);

使用 IViewObject,您可以创建当前视口的屏幕截图。我使用一个技巧来创建网页(没有任何框架)或框架文档的屏幕截图。

  1. 使用scrollWidth/scrollHeight/scrollLeft/scrollTop计算完整文档大小(检查IHtmlDocument2和IHtmlDocument3接口)
  2. 锁定窗口更新并将文档调整为计算出的完整尺寸
  3. 使用 IViewObject 创建快照(上面的代码似乎没问题)
  4. 将文档恢复到原始大小并解锁窗口更新

注意当文档非常大时,您应该小心执行此操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 WebBrowser 渲染到设备上下文? 的相关文章

随机推荐