WPF作为IHTMLPainter控件

时间:2009-11-19 14:53:19

标签: wpf activex

我需要在IE中托管WPF控件,因此我正在尝试实现IHTMLPainter和IElementBehavior接口。我想构建我的自定义行为并在IE中使用它,但问题是如何通过使用IntPtr hdc参数来绘制WPF控件。 可能我可以通过以下代码获得Drawing.Graphics:

Graphics.FromHdc(hdc);

但我不确定这是最好的方法。请指教

2 个答案:

答案 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()方法中,执行以下操作:

  1. 创建与rcUpdate
  2. 对应的System.Drawing.Bitmap
  3. BitBlt从指定的DC进入System.Drawing.Bitmap
  4. ImageSoure构建System.Drawing.Bitmap(有关详细信息,请参阅最近的SO答案)
  5. 使用视口/视图框从ImageBrush构建BitmapSource,视频/视图框将其放置在与rcUpdate对应的视觉部分后面
  6. 将您的根视觉背景设置为ImageBrush
  7. 在根目录上设置RenderTransform,以便rcUpdate部分从(0,0)开始
  8. 将根视觉渲染为rcUpdate大小的RenderTargetBitmap
  9. BitBlt RenderTargetBitmap到DC的rcUpdate区域
  10. 这应该运行良好,易于实现,并且适用于任何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,然后执行以下任一操作。

  1. 在运行时添加WPF控件作为UserControl的成员。
  2. 使用控件的窗口句柄(HWND)执行WPF活动。
  3. 或者,您可以使用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)。

    IOleWindow Interface @ MSDN
    IHTMLWindow2 Interface @ MSDN