我需要在IE中托管WPF控件,因此我正在尝试实现IHTMLPainter和IElementBehavior接口。我想构建我的自定义行为并在IE中使用它,但问题是如何通过使用IntPtr hdc参数来绘制WPF控件。 可能我可以通过以下代码获得Drawing.Graphics:
Graphics.FromHdc(hdc);
但我不确定这是最好的方法。请指教
答案 0 :(得分:1)
我假设您希望能够在MSHTML上下文中使用WPF的高级功能。在这种情况下,Graphics.FromHdc(hdc);
将无法为您完成任务。生成的Graphics
对象将无法接收WPF内容,因为WPF使用保留模式系统,而其MILCore呈现引擎使用Direct3D而非GDI +。
我会给你一个确定的方法来在IHTMLPainter中使用WPF功能,以及指向另一种方式的指针,如果你可以让它工作,它可能会更快。
位图复制解决方案
一个简单的解决方案是简单地将MSHTML提供的背景复制到ImageBrush中,使用RenderTargetBitmap让WPF渲染到位图,然后将其复制回设备。
为此,使用Background属性(例如Grid或Border)在任何Visual子类中构建WPF内容,然后在IHTMLPainter.Draw()方法中,执行以下操作:
System.Drawing.Bitmap
BitBlt
从指定的DC进入System.Drawing.Bitmap
ImageSoure
构建System.Drawing.Bitmap
(有关详细信息,请参阅最近的SO答案)ImageBrush
构建BitmapSource
,视频/视图框将其放置在与rcUpdate对应的视觉部分后面RenderTransform
,以便rcUpdate部分从(0,0)开始RenderTargetBitmap
BitBlt
RenderTargetBitmap
到DC的rcUpdate区域这应该运行良好,易于实现,并且适用于任何WPF内容,包括3D,BitmapEffects等高级功能。唯一的缺点是这两个位图副本可能会使某些内容变慢。
请注意,如果您知道您的WPF Visual完全不透明,您可以完全跳过步骤1-5,只需将Visual渲染为RenderTargetBitmap并将其BitBlt设置为该设备。
Direct3D可能性(部分解决方案)
显然,在渲染过程中避免所有这些位图复制会更快。这很可能是可能的,但我只能给你一些想法指出方向 - 这将需要大量的试验和错误,并且可能需要一些无证的调用才能使其正常工作。
由于WPF渲染使用Direct3D,显然你更喜欢从MSHTML获取Direct3D表面并在其上绘制。这样做需要两件事:从MSHTML获取表面,并让MILCore绘制它。
IHTMLPainter
有一个标记HTMLPAINTER_3DSURFACE
来在其GetPainterInfo调用中请求Direct3D表面,但我找不到任何有关如何使用HTMLPAINTER_3DSURFACE
的示例。我怀疑它可以通过一些试验和错误来解决。
我没有找到任何办法让WPF的原生组件“MILCore”接受Direct3D表面来绘制而不是hWnd。 MILCore没有文档,设置渲染树的唯一公共API HwndSource似乎无法完成这项工作。
答案 1 :(得分:0)
通过IHTMLPainter和IElementBehavior渲染行为旨在改变或补充页面中现有元素的显示,而不是为用户控件呈现内容。如果您希望在页面中使用WPF控件,则不需要这样做。相反,请考虑使用ActiveX支持创建一个空白窗口UserControl,然后执行以下任一操作。
或者,您可以使用Silverlight进行用户控制。 Silverlight有很好的WPF显示功能子集,甚至手动构建的Silverlight内容也比试图让.NET Windows + ActiveX Hosting + WPF工作更容易管理。
如果我误解了你的问题并且你真的打算使用WPF在元素行为中执行绘图活动,那么Graphics.FromHdc()是获得可用Graphics对象的可接受方式。您应该附加到Draw()回调中指定的HDC。
Draw Method (IHTMLPainter) @ MSDN
如果您的WPF活动涉及整个视口,您还可以附加到文档视图的窗口句柄(HWND)(通过IOleWindow检索)。为此,可以将window对象强制转换为IOleWindow(参见IHTMLWindow2)。