Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.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
Wpf 在DirectX内容上覆盖WinForms控件_Wpf_Winforms_Directx_Transparency_Gdi - Fatal编程技术网

Wpf 在DirectX内容上覆盖WinForms控件

Wpf 在DirectX内容上覆盖WinForms控件,wpf,winforms,directx,transparency,gdi,Wpf,Winforms,Directx,Transparency,Gdi,我正在尝试用图形控件创建一个图形库。该控件允许添加覆盖控件。控件上的图形使用DirectX,是库的一部分,而叠加控件由库的最终用户提供,这些用户不是图形专家。因此,稳定性和方便的API是最重要的问题 出于技术原因,我需要通过DirectX直接在控件上显示图形,并且无法使用另一个框架作为WPF主持DirectX场景(有关更多信息,请参阅我前面的问题:) 我认为最有问题的问题是: 控件本身区域内的透明度(和半透明度…) 覆盖控件上的动画:这就是为什么控件光栅化(例如,通过WPF)不是一个选项 我

我正在尝试用图形控件创建一个图形库。该控件允许添加覆盖控件。控件上的图形使用DirectX,是库的一部分,而叠加控件由库的最终用户提供,这些用户不是图形专家。因此,稳定性和方便的API是最重要的问题

出于技术原因,我需要通过DirectX直接在控件上显示图形,并且无法使用另一个框架作为WPF主持DirectX场景(有关更多信息,请参阅我前面的问题:)

我认为最有问题的问题是:

  • 控件本身区域内的透明度(和半透明度…)
  • 覆盖控件上的动画:这就是为什么控件光栅化(例如,通过WPF)不是一个选项
我迄今为止的努力:

  • 在许多帖子讨论了类似的问题之后,我决定使用WS_EX_TRANSPARENT。我很惊讶地看到,虽然是,但我可以在覆盖控件的透明区域下看到DirectX内容。但是,覆盖控件没有显示,除非我调整了窗口的大小,然后它会闪烁并再次消失。下面是覆盖控件的代码:

    class GDIGraphicsControl : UserControl
    {
      private const int WS_EX_TRANSPARENT = 0x20;
    
      protected override CreateParams CreateParams
      {
        get
        {
          CreateParams p = base.CreateParams;
          p.ExStyle |= WS_EX_TRANSPARENT;
          return p;
        }
      }
    
      public GDIGraphicsControl()
      {
        this.Dock = DockStyle.Fill;
      }
    
      protected override void OnPaintBackground(PaintEventArgs e)
      {
        // Do nothing
      }
    
      protected override void OnPaint(PaintEventArgs e)
      {
        for (int i = 0; i < 10; ++i)
        {
          int alpha = 25 * i;
          int yPos = 10 * i;
          e.Graphics.FillRectangle(
            new SolidBrush(Color.FromArgb(alpha, Color.Green)),
            5, 5 + yPos, 100, 10);
        }
        e.Graphics.FillEllipse(new SolidBrush(Color.Red), 110, 5, 100, 100);
      }
    }
    
  • 我尝试添加一个简单的覆盖按钮,以检查在没有使用透明度时是否存在问题(请参见上面的代码)。按钮不会闪烁,但我看到屏幕上的按钮不是垃圾,直到第一次调整控件的大小-然后按钮正确显示

  • 我试图使子覆盖控件无效,但无效。我尝试在父对象的OnPaint和子对象的OnPaint中使其无效,以创建消息泵渲染效果,但没有效果。将控件的样式设置为“父渲染控件”中的样式无法解决问题,并导致背景以黑色闪烁

  • 我也使用WPF进行了一些尝试,但问题已经足够长了,现在没有困难了

    现在回答问题:

  • 有人能解释一下GDI是如何覆盖DirectX图形的吗?尤其是我不理解它,因为我知道WinForms transparency的工作原理是子控件在父设备上下文上渲染,而DirectX有一个硬件渲染上下文。这是否意味着DirectX纹理被复制回软件

  • 为什么重写CreateParams会导致控件闪烁,以及如何防止闪烁

  • 这些透明方法(覆盖CreateParams,BackColorTransparency=True,Control.SetStyle+覆盖OnPainBackground)的性能成本是多少?底层图形的高效渲染非常重要,但我不关心覆盖性能(轻量级动画除外)


  • 我在这方面做了很多研究,我得出结论,空域是一条出路。我已经收集了来自web上许多项目的源代码,并将它们放在一个项目中,该项目允许您将WPF与XNA集成。我还做了一个纯DirectX版本,但说实话,XNA版本更简单,更适合C。我没有足够的空间在这里发布所有的细节,但是你可以并且可能知道从那里走到哪里。祝你好运

    我在这方面做了很多研究,我得出结论,空域是一条必经之路。我已经收集了来自web上许多项目的源代码,并将它们放在一个项目中,该项目允许您将WPF与XNA集成。我还做了一个纯DirectX版本,但说实话,XNA版本更简单,更适合C。我没有足够的空间在这里发布所有的细节,但是你可以并且可能知道从那里走到哪里。祝你好运

    非常感谢。实际上,我已经成功地使用ElementHost将WPF控件放置在DirectX内容上,并将BackColorTransparent设置为True。不过,我也希望支持WinForms控件。WPF ElementHost(我猜也是从您的源代码弹出的)不能与同一层次结构级别中的其他覆盖WinForms控件很好地互操作(它隐藏了它下面的WinForms控件,甚至在透明区域中)。此外,透明的WinForms闪烁(没有任何WPF控件,如您的示例中所示),并且您的源代码没有处理此类WinForms控件。您是否也有一个DirectX上WinForms的示例?或者根据您的经验为我理解问题提供建议?非常感谢。实际上,我已经成功地使用ElementHost将WPF控件放置在DirectX内容上,并将BackColorTransparent设置为True。不过,我也希望支持WinForms控件。WPF ElementHost(我猜也是从您的源代码弹出的)不能与同一层次结构级别中的其他覆盖WinForms控件很好地互操作(它隐藏了它下面的WinForms控件,甚至在透明区域中)。此外,透明的WinForms闪烁(没有任何WPF控件,如您的示例中所示),并且您的源代码没有处理此类WinForms控件。您是否也有一个DirectX上WinForms的示例?或者根据您的经验为我理解问题提供建议?
    public partial class RenderingForm : Form
    {
      public RenderingForm()
      {
        InitializeComponent();
    
        ControlStyles styles =
          ControlStyles.AllPaintingInWmPaint |
          ControlStyles.OptimizedDoubleBuffer |
          ControlStyles.ResizeRedraw |
          ControlStyles.UserPaint |
          ControlStyles.Opaque;
        this.SetStyle(styles, true);
    
        Button button = new Button()
        {
          Text = "Just a button",
          Left = 5,
          Top = 210,
          Width = 200
        };
    
        this.Controls.Add(button);
        this.Controls.Add(new GDIGraphicsControl());
      }
    
      protected override void OnPaintBackground(PaintEventArgs e)
      {
        // Do nothing
      }
    
      protected override void OnPaint(PaintEventArgs e)
      {
        e.Graphics.Clear(Color.Blue);
    
        this.Invalidate();
    
        base.OnPaint(e);
      }
    }