在DirectX内容上覆盖WinForms控件 [英] Overlay WinForms controls on DirectX content

查看:87
本文介绍了在DirectX内容上覆盖WinForms控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a graphics library with graphics control. The control enables adding overlay controls. The graphics on the control uses DirectX and is part of the library, while the overlay controls are provided by end users of the library which are not graphics experts. Thus stability and convenient API are the most important issues.

出于技术原因,我需要直接在控件上显示DirectX的图形,并且不能使用其他框架托管DirectX场景。作为WPF(有关更多信息,请参阅我之前的问题: WPF上的立体3D )。

For technical reasons I need to show the graphics by DirectX directly on the control and cannot host the DirectX scene using another framework as WPF (For more information see my previous question: Stereoscopic 3D on WPF).

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

I think the most problematic issues are:


  • 透明度(和半透明)。

  • 叠加控件上的动画:这就是为什么不能选择控件栅格化(例如,通过WPF)的原因。

直到现在我的尝试:


  1. 在大量讨论之后类似的问题,我决定使用WS_EX_TRANSPARENT。我很惊讶地看到,尽管空域问题,我可以在覆盖控件的透明区域下看到DirectX内容。但是,除了我调整窗口大小时,没有显示覆盖控件-然后它闪烁并再次消失。这是叠加层控件的代码:

  1. Following the lot of posts discussed similar issues I decided to use WS_EX_TRANSPARENT. I was surprised to see that although the Airspace issue, I can see the DirectX content under the transparent regions of the overlay control. However the overlay control was not shown except for when I resized the window - then it blinks and disappears again. Here is the code of the overlay control:

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);
  }
}


  • 要分析闪烁的问题,我试图使事情变得简单。首先出于调试目的,我尝试使用GDI呈现而不是DirectX。我实现了它,使其与DirectX呈现非常相似-特别是每个OnPaint()中的Form.SetStyle和Invalidate()调用,我认为这是导致此问题的原因。仅GDI渲染中也确实存在该问题。以下是GDI渲染的父控件代码:

  • To analyze the blinking problem I tried to make things simpler. First for debugging purpose I tried to use GDI rendering instead of DirectX. I implemented it such that it will be very similar to the DirectX rendering - especially the Form.SetStyle and the Invalidate() call in every OnPaint() which I thought to be the cause to the problem. The problem do exist also in GDI-only rendering. Here is the GDI-rendering parent control code:

    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);
      }
    }
    


  • 我尝试添加一个简单的叠加按钮在不使用透明度的情况下检查问题是否存在(请参见上面的代码)。该按钮没有闪烁,但是在第一次调整控件大小之前,我没有看到该按钮,而是在屏幕上看到垃圾-然后该按钮正确显示。

  • I tried to add a simple overlay Button to check if the problem exist when no transparency is used (see in the above code). The button doesn't blink, but instead of the button I see garbage on the screen until resizing the control first time - then the button appears correctly.

    I试图使子叠加控件无效,但它没有任何效果。我试图在父级的OnPaint和子级的OnPaint中使它无效,以创建消息泵渲染效果,但该效果无效。在父渲染控件中设置控件的样式不能解决问题,并导致背景以黑色闪烁。

    I tried to invalidate the child overlay controls but it has no effect. I tried to invalidate it both in parent's OnPaint and in the child OnPaint to create the message-pump rendering effect and it has no effect. Setting the control's style as in parent rendering control didn't resolve the problem and caused the background to blink in black.

    我也使用WPF进行了一些尝试,但问题现在已经足够长,没有硬空域问题 ...

    I also performed some tries using WPF but the question is long enough for now without hard Airspace issue...

    现在开始提问:


    1. 有人可以解释在DirectX图形上进行GDI叠加的工作方式吗?尤其是我听不懂,因为我知道WinForms透明性是通过子控件在父级的设备上下文中呈现而起作用的-DirectX具有硬件呈现上下文。

    1. Can someone explain how does GDI overlay over DirectX graphics work? Especially I don't understand it because I know that WinForms transparency is working by that the children controls render on the parent's Device Context - and DirectX has a hardware rendering context. Does it mean that the DirectX texture is copied back to software?

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

    Why does overriding the CreateParams causes the Control to blink and how to prevent it?

    这些透明方法(重写CreateParams,BackColorTransparency = True,Control.SetStyle + override OnPainBackground)的性能成本是多少?至关重要的是,可以有效地渲染基础图形,但我不在乎覆盖性能(轻量级动画除外)。

    What are performance cost do those transparency methods (overriding CreateParams, BackColorTransparency = True, Control.SetStyle+override OnPainBackground)? It is of high importance that the underlying graphics will be rendered efficiently but I don't care about the overlay performance (except for lightweight animation).


    推荐答案

    我在这一领域做了很多研究,得出的结论是空域是未来的发展之路。我已经从网络上的许多项目中收集了资源,并将它们放到一个项目中,使您可以将WPF与XNA集成。我还做了一个纯DirectX的版本,但是说实话,XNA版本更加简单,更适合C#。我没有足够的空间在此处发布所有详细信息,但是您可以从我的网站上下载演示网站,并且可能会弄清楚该去哪里。祝你好运!

    I've done a LOT of research in this area and I've come to the conclusion that Airspace is the way to go. I've collected sources from numerous projects around the web and put them into a single project that allows you to integrate WPF with XNA. I've also done a version of this that was pure DirectX, but to be honest the XNA version is a lot more straightforward and better suited to C#. I don't have enough room to post all the details here but you can download the demo from my website and probably figure out where to go from there. Good luck!

    这篇关于在DirectX内容上覆盖WinForms控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆