【发布时间】:2012-06-08 16:34:17
【问题描述】:
我想将网页(即TWebBrowser)呈现给设备上下文。我想使用 Internet Explorer 的布局引擎将内容呈现到设备上下文(即元文件、pdf 元文件)。
从 Internet Explorer 9 开始,IHTMLElementRender 接口不再支持:
IHTMLElementRender 接口
使用此接口将元素的内容绘制到指定的设备上下文,通常是打印机。
成员
IHTMLElementRender 接口继承自 IUnknown 接口,但没有其他成员。
以至于他们不再提到DrawToDC method 甚至存在:
IHTMLElementRender::DrawToDC Method
已弃用。将元素的内容绘制到指定的设备上下文。
语法
HRESULT DrawToDC( HDC hDC );参数
- hDC
[在] HDC 指定要绘制到的设备,通常是打印机。返回值
如果成功则返回 S_OK,否则返回错误值。
备注
从 Windows Internet Explorer 9 开始,此方法已被弃用,不应使用。
对于某些打印机,运行 IHTMLElementRender::DrawToDC 可能会导致问题。您可以确保 IHTMLElementRender::DrawToDC 在所有打印机上正常工作,方法是先运行IHTMLElementRender::SetDocumentPrinter 方法,然后将修改后的设备上下文传递给 IHTMLElementRender::DrawToDC。。 p>
注意:我引用了所有文档,以便在 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;
使用IViewObject 接口
我已尝试转换为使用IViewObject(例如How to render HTML element without using web browser?):
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;
这段代码的问题在于它只渲染了浏览器的可见区域(即没有滚动的内容):
我需要渲染 整个 网页(例如用于打印)。
我尝试将draw aspect 从DVASPECT_CONTENT(就像this example 所做的那样)更改为DVASPECT_DOCPRINT:
DVASPECT_DOCPRINT
在屏幕上提供对象的表示,就好像它是使用“文件”菜单中的“打印”命令打印到打印机一样。所描述的数据可能代表一系列页面。
结果相同;而不是渲染页面,只渲染可见部分:
如何让IE9渲染引擎渲染?
我还尝试使用不同的索引以及DVASPECT_DOCPRINT。虽然IViewObject 没有记录在案,但也许这就是您打印不同“pages”的方式:
view.Draw(DVASPECT_DOCPRINT, 1, ...);
view.Draw(DVASPECT_DOCPRINT, 2, ...);
view.Draw(DVASPECT_DOCPRINT, 3, ...);
...
view.Draw(DVASPECT_DOCPRINT, n, ...);
但是 WebBrowser 并不关心索引是什么;只渲染当前的 View(我认为在使用 IViewObject 时这是有道理的)。
如何将浏览器呈现到设备上下文?
注意:该问题带有delphi 标记,但该问题中没有特定于delphi 的内容。
更新:我还尝试了 aspect 和 index 的其他组合:
view.Draw(DVASPECT_CONTENT, -1, ...);
view.Draw(DVASPECT_DOCPRINT, -1, ...);
view.Draw(DVASPECT_CONTENT, 0, ...);
view.Draw(DVASPECT_DOCPRINT, 0, ...);
【问题讨论】:
-
根据this,您在正确的轨道上,需要调整浏览器控件的大小(暂时)。未测试。
-
TOndrej 在这种情况下,浏览器(控件)对齐/停靠到客户端表单,该表单受限于用户监视器的大小。就像 Internet Explorer 本身一样。所以我想知道 Internet Explorer 如何管理到
Print。 -
也许您可以创建一个临时的不可见浏览器控件并将内容复制到其中,或者重用现有控件并尝试使用 WM_SETREDRAW、LockWindowUpdate 等技巧来避免可见效果。
-
@TOndrej 调整浏览器控件的大小在某些情况下可能会起作用,但在其他情况下,它可能会给您带来意想不到的结果,即如果您调整浏览器控件本身的大小,HTML 内容可能会更改其布局。
-
@Ian,就像 TOndrej 提到的,如果不调整浏览器的大小,您似乎无法获得完整的内容。顺便说一句,您可能希望在宽度和高度计算中包含正文的左、右、上和下边距。
标签: delphi winapi internet-explorer-9 rendering delphi-5