Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带HWND子级的WPF渲染问题_Wpf_Rendering_Webbrowser Control_Hwnd - Fatal编程技术网

带HWND子级的WPF渲染问题

带HWND子级的WPF渲染问题,wpf,rendering,webbrowser-control,hwnd,Wpf,Rendering,Webbrowser Control,Hwnd,我想可以肯定地说,WPF将其内容呈现为窗口背景。没有传统HWND意义上的子窗口。所以,当一个人在WPF应用程序中引入基于HWND的东西时,比如WebBrowser,就视觉外观而言,事情就开始出错了 假设一个窗口有两个子网格,WebBrowser和其他东西,例如TextBox。如果WebBrowser是一个红色圆圈,则文本框将呈现在其上方。对于WebBrowser,任何地方都找不到文本框。这是因为TextBox被渲染为主窗口的背景,而WebBrowser实际上是主窗口的HWND子窗口,遮挡了背景

我想可以肯定地说,WPF将其内容呈现为窗口背景。没有传统HWND意义上的子窗口。所以,当一个人在WPF应用程序中引入基于HWND的东西时,比如WebBrowser,就视觉外观而言,事情就开始出错了

假设一个窗口有两个子网格,WebBrowser和其他东西,例如TextBox。如果WebBrowser是一个红色圆圈,则文本框将呈现在其上方。对于WebBrowser,任何地方都找不到文本框。这是因为TextBox被渲染为主窗口的背景,而WebBrowser实际上是主窗口的HWND子窗口,遮挡了背景

所以一切都不好。一个人如何达到期望的行为?我想在WebBrowser上渲染文本框。有人遇到过这个问题吗

我正在考虑使用第二个透明的顶级无边界WPF窗口,重新设置它的父窗口,以便主窗口拥有它,并使用其他一些技巧来实现它

在我深入研究之前,我想知道是否有人有一个明显的或更简单的解决方案


梅莱克更新
我向任何能够发布Ray Burns Answer
AirRepair
实现的人提供这笔赏金。我自己试过了,但没有成功。

通读一遍。

如果你是专门针对web浏览器的,有过几次尝试。创建了基于Chrome的优秀解决方案。

建议的解决方案

我建议使用带有此签名的简单“AirRepair”类:

public class AirRepair : Decorator
{
  public HwndHost Win32Host ... // DP bound to HwndHost
  public Geometry RepairArea ... // Default is entire decorated control,
                                 // or use OpacityMask
}
使用这种方式:

<Grid>
  <WebBrowser x:Name="browser" ... />

  <AirRepair Win32Host="{Binding ElementName=browser}"
             Margin="10" HorizontalAlignment="Left" ...>
    <TextBox ... />
  </AirRepair>
</Grid>
应使用
ui元素.LayoutUpdated
事件使其保持最新

计算hRgn和不透明度

可选:如果仅支持矩形修复区域,则忽略

当设置了
RepairArea
OpacityMask
且子hWnd存在时,使用
RenderTargetBitmap
使用
OpacityMask
绘制
RepairArea
,然后从中创建hRgn。如果
RepairArea
为空,请使用矩形。如果
OpacityMask
为空,则使用黑色。
RenderTargetBitmap
大小是通过将AirRepair装饰器的坐标转换为设备坐标来设置的。请注意,这无法正确处理变量
OpacityMask
,例如动画笔刷或
VisualBrush
Visual
正在更改

在子hWnd上绘制内容

使用
VisualBrush
,其
VisualBrush
是AirRepair装饰器,而不是装饰控件。这允许在不更改内容的情况下替换装饰控件

childHwndSource.RootVisual =
  new Border
  {
    Background = new VisualBrush
    {
      Visual = this,
      ViewBoxUnits = BrushMappingMode.Absolute,
      ViewPortUnits = BrushMappingMode.Absolute,
    }
  };
转发鼠标消息

使用
HwndSource.AddHook
添加钩子,然后使用Win32
PostMessage
将钩子添加到容器:

childHwndSource.AddHook((hwnd, msg, wParam, lParam, handled) =>
{
  // Check if message needs forwarding and update parameters if necessary
  switch(msg)
  {
    default:
      return;  // Not recognized - do not forward

    case WM_MOUSEMOVE:
    ...
  }
  var target = PresentationSource.FromVisual(this).CompositionTarget as HwndTarget;
  if(target!=null)
    Win32Methods.PostMessage(target.Handle, msg, wParam, lParam);
};

如果您正在寻找一个快速简单的解决方案,只需使用弹出控件,下面是一个示例


好的,谢谢。这篇文章除了更详细地解释我已经假设的内容之外没有任何帮助。我想我将不得不尝试两个WPF窗口,看看我是否能达到我想要的效果。是的,我实际上是针对一个web浏览器,但Chris的解决方案对于我试图实现的目标来说似乎是一个过火了。我一定会认为这是一个选择,因为它看起来真的很棒。谢谢好的,起初我认为这是一个完整的解决方案,但重新阅读后,我意识到这是一个分散在各地的解决方案;-)让我把谜题拼凑在一起(如果我目前的解决方案不太可靠,我可能会这么做)。但是,如果所有的代码片段都是从你的头上掉下来的,或者你真的是从一个工作的解决方案中粘贴的,这让我很困惑?如果是前者,那就太棒了,但你怎么知道它会起作用呢?如果是后者,为什么根本没有代码链接?;-)无论如何,非常感谢。这看起来很有希望。代码片段都是我脑子里想不出来的,但每一个都是从我以前写过的代码中提取出来的。我以前从未以这种方式解决过空域问题,但我所描述的每一件事都是我实际做过的,我很有信心它能够成功。我考虑这个设计已经很长时间了,但还没有时间这样把它组合起来。当我看到你的问题时,我决定分享这个设计,因为它看起来比你正在考虑的更简单、更灵活。你有没有实现过它?在这种情况下,它起作用了吗?不,我从来没有实施过,因为即使它可能达到最初问题的目的,我的需求也发生了变化,标准WebBrowser不再是我的解决方案。我最终使用了Awesomium和Chris Cavanagh的WPF包装器。它工作得非常好。对我来说再也没有HWND问题了。Awesomium从那以后一直在发展,现在它拥有自己的WPF包装器。如果WebBrowser是您主要关心的问题,我建议您查看Awesomium。感谢您的建议,不幸的是,
WebBrowser
不是我的主要问题,它是一堆
WindowsFormsHost
。我现在已经用一个自定义的
弹出控件解决了这个问题,但是我对这个解决方法不是很满意。我已经在使用一个自定义的非最上面的“弹出”控件,它可以跟随一个屏幕,但是使用“弹出”是非常有技巧的,而且很难调试,因为它可以在调试器上结束,即使使用非最上面的补丁。还有其他一些小问题。。
childHwndSource.AddHook((hwnd, msg, wParam, lParam, handled) =>
{
  // Check if message needs forwarding and update parameters if necessary
  switch(msg)
  {
    default:
      return;  // Not recognized - do not forward

    case WM_MOUSEMOVE:
    ...
  }
  var target = PresentationSource.FromVisual(this).CompositionTarget as HwndTarget;
  if(target!=null)
    Win32Methods.PostMessage(target.Handle, msg, wParam, lParam);
};