简体   繁体   中英

Drawing over a 3D rendered scene using C#

UPDATE: Since originally asking this question, I have changed my approach slightly. Rather than drawing using System.Drawing.Graphics , I am hosting a WPF user control with an InkCanvas. That does everything I need it to do. The problem still is that I cannot get the background of the ElementHost to be transparent. I see the same black square I was seeing before.

ORIGINAL QUESTION: I have a C# WinForms application that renders a 3D scene using Ogre3D to a panel in the form using that panel's handle. I am trying to add the ability to draw on top of that scene (imagine Madden drawing over the TV screen) using C#'s System.Drawing.Graphics .

I'm using the BufferedGraphics class to do this. As a test, I'm trying to simply draw a rectangle on top of the 3D scene. Below is a snippet of the code I'm using to set everything up.

namespace TestApp
{
    public partial class TestForm
    {
        private BufferedGraphics graphicsBuffer;
        private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;

        public TestForm()
        {
            InitializeComponent();
            UpdateGraphicsBuffer();
        }

        private void UpdateGraphicsBuffer()
        {
            bufferContext.MaximumBuffer = new Size(panelRender.Width + 1, panelRender.Height + 1);
            graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panelRender.Handle), new Rectangle(49, 49, 100, 100));
            graphicsBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        }

        private void TestForm_Load(object sender, EventArgs e)
        {
            graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red), 50, 50, 50, 50);
        }
    }
}

I've left out a lot of the proprietary code (there is a call to graphicsBuffer.Render(); in part of that proprietary code) and renamed some stuff but hopefully what I have provided will give you the gist. Also, the 3D scene is also using panelRender.Handle to draw into that panel, and the panelRender.BackColor is black.

In a nutshell, what I am seeing is a chunk of my 3D scene missing (specifically a 100x100 chunk) with the 50x50 red rectangle drawn inside it, as pictured here:

绘画问题

Obviously I don't want to lose the scene that I'm trying to draw on top of. Right now, I'm at a loss as to why this is happening. Is what I'm trying to do just not possible? If any additional information/code is needed, I will be happy to provide it, if possible.

EDIT: To try and simplify matters, I created a really simple WinForms app that has a single panel and used the code above to recreate the issue. The code-behind for that is here:

using System.Drawing;
using System.Windows.Forms;

namespace DoubleBufferTest
{
    public partial class Form1 : Form
    {
        private BufferedGraphics graphicsBuffer = null;
        private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;

        public Form1()
        {
            this.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.UpdateStyles();
            InitializeComponent();
            UpdateGraphicsBuffer();
        }

        private void UpdateGraphicsBuffer()
        {
            bufferContext.MaximumBuffer = new Size(panel1.Width + 1, panel1.Height + 1);
            graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panel1.Handle), new Rectangle(10, 10, 50, 50));
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red, 3.0f), 20, 20, 10, 10);
            graphicsBuffer.Render();
        }
    }
}

The panel's backcolor is set to transparent. Here is the result:

测试应用

That black square corresponds to the graphics buffer that is getting allocated by the context. Why it always shows up as black is basically what is confusing me now...

What I think you should do is use the SetStyle method to set the background to transparent. More info at https://msdn.microsoft.com/en-us/library/system.windows.forms.control.setstyle%28v=vs.110%29.aspx

Thank you to @Ron Beyer for answering this for me in a different question I posted.

So I was on the right track with the ElementHost control, but because of the transparency issues, Ron suggested that I try using a new WPF window that I could overlay on top of the application ( link ). The WPF window's background is set to transparent, so drawing on the InkCanvas results in the desired effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM