Two Windows Forms controls on one form

Hello everyone,

I am using MonoGame for my game. Now with my editors I have a problem. I have to use two Windows Forms controls on one form.

This is my code for the control:

public class EditorControl : Control, IGraphicsDeviceService
{
private static readonly Color designerBackColor = Color.FromArgb(240, 240, 240);

    private static GraphicsDevice graphicsDevice;
    private static PresentationParameters parameters;

    public GraphicsDevice GraphicsDevice
    {
        get
        {
            return graphicsDevice;
        }
    }

    public event EventHandler OnInitialize;
    public event EventHandler OnDraw;

    protected void Initialize()
    {
        if (OnInitialize != null)
            OnInitialize(this, null);
    }

    protected void Draw()
    {
        if (OnDraw != null)
            OnDraw(this, null);
    }

    protected override void OnCreateControl()
    {
        if (!DesignMode)
        {
            if (parameters == null && graphicsDevice == null)
            {
                CreateGraphicsDevice(Handle, ClientSize.Width, ClientSize.Height);
            }

            Initialize();
        }

        base.OnCreateControl();
    }

    private static void CreateGraphicsDevice(IntPtr windowHandle, int width, int height)
    {
        parameters = new PresentationParameters
        {
            BackBufferWidth = Math.Max(width, 1),
            BackBufferHeight = Math.Max(height, 1),
            BackBufferFormat = SurfaceFormat.Color,
            DepthStencilFormat = DepthFormat.Depth24,
            DeviceWindowHandle = windowHandle,
            PresentationInterval = PresentInterval.Immediate,
            IsFullScreen = false
        };

        graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.Reach, parameters);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (CanDraw())
        {
            Draw();
            FinishDraw();
        }
        else
        {
            e.Graphics.Clear(designerBackColor);
        }
    }

    private bool CanDraw()
    {
        if (graphicsDevice == null || IsDeviceAvailable() == false)
            return false;

        GraphicsDevice.Viewport = new Viewport
        {
            X = 0,
            Y = 0,
            Width = ClientSize.Width,
            Height = ClientSize.Height,
            MinDepth = 0,
            MaxDepth = 1
        };

        return true;
    }

    private void FinishDraw()
    {
        try
        {
            Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width, ClientSize.Height);

            GraphicsDevice.Present(sourceRectangle, null, Handle);
        }
        catch
        {
            // GULP
        }
    }

    private bool IsDeviceAvailable()
    {
        bool deviceNeedsReset;

        switch (graphicsDevice.GraphicsDeviceStatus)
        {
            case GraphicsDeviceStatus.Lost:
                return false;
            case GraphicsDeviceStatus.NotReset:
                deviceNeedsReset = true;
                break;
            default:
                deviceNeedsReset = (ClientSize.Width > parameters.BackBufferWidth) || (ClientSize.Height > parameters.BackBufferHeight);
                break;
        }

        if (deviceNeedsReset)
        {
            try
            {
                ResetDevice(ClientSize.Width, ClientSize.Height);
            }
            catch
            {
                return false;
            }
        }

        return true;
    }

    protected override void OnPaintBackground(PaintEventArgs p) { }

    public event EventHandler<EventArgs> DeviceCreated;
    public event EventHandler<EventArgs> DeviceDisposing;
    public event EventHandler<EventArgs> DeviceReset;
    public event EventHandler<EventArgs> DeviceResetting;

    protected override void Dispose(bool disposing)
    {
        if (graphicsDevice != null)
        {
            if (DeviceDisposing != null)
                DeviceDisposing(this, EventArgs.Empty);

            graphicsDevice.Dispose();
        }

        graphicsDevice = null;

        base.Dispose(disposing);
    }

    public void ResetDevice(int width, int height)
    {
        if (DeviceResetting != null)
            DeviceResetting(this, EventArgs.Empty);

        parameters.BackBufferWidth = Math.Max(parameters.BackBufferWidth, width);
        parameters.BackBufferHeight = Math.Max(parameters.BackBufferHeight, height);

        graphicsDevice.Reset(parameters);

        if (DeviceReset != null)
            DeviceReset(this, EventArgs.Empty);
    }
}

This code works fine in XNA, but not with MonoGame. As GraphicsDevice.Present does not take any parameters. Any idea how I could make multiple graphics device controls possible in MonoGame?

Thanks,
Christian

Use the normal Present() and combine this with a SwapChainRenderTarget(handle).

Thanks for the idea. I am sure I did something wrong here as all I get is some weird flickering. I added a new method CreatedSwapChainRenderTarget() that I call whenever I the control is initialized or its size is changed.
Now set the RenderTarget right before any drawing occurs.

This is my code:

public class EditorControl : Control, IGraphicsDeviceService
{
private static readonly Color designerBackColor = Color.FromArgb(240, 240, 240);

    private static GraphicsDevice graphicsDevice;
    private static PresentationParameters parameters;
    SwapChainRenderTarget target;

    public GraphicsDevice GraphicsDevice
    {
        get
        {
            return graphicsDevice;
        }
    }

    public event EventHandler OnInitialize;
    public event EventHandler OnDraw;

    protected void Initialize()
    {
        if (OnInitialize != null)
            OnInitialize(this, null);
    }

    protected void Draw()
    {
        if (OnDraw != null)
            OnDraw(this, null);
    }

    protected override void OnCreateControl()
    {
        if (!DesignMode)
        {
            if (parameters == null && graphicsDevice == null)
            {
                CreateGraphicsDevice(Handle, ClientSize.Width, ClientSize.Height);
            }
            CreateSwapChainRenderTarget();
            Initialize();
        }

        base.OnCreateControl();
    }

    private static void CreateGraphicsDevice(IntPtr windowHandle, int width, int height)
    {
        parameters = new PresentationParameters
        {
            BackBufferWidth = Math.Max(width, 1),
            BackBufferHeight = Math.Max(height, 1),
            BackBufferFormat = SurfaceFormat.Color,
            DepthStencilFormat = DepthFormat.Depth24,
            DeviceWindowHandle = windowHandle,
            PresentationInterval = PresentInterval.Immediate,
            IsFullScreen = false
        };

        graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.Reach, parameters);
        
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (CanDraw())
        {
            Draw();
            FinishDraw();
        }
        else
        {
            e.Graphics.Clear(designerBackColor);
        }
    }

    private bool CanDraw()
    {
        if (graphicsDevice == null || IsDeviceAvailable() == false)
            return false;

        GraphicsDevice.Viewport = new Viewport
        {
            X = 0,
            Y = 0,
            Width = ClientSize.Width,
            Height = ClientSize.Height,
            MinDepth = 0,
            MaxDepth = 1
        };
       GraphicsDevice.SetRenderTarget(target);

        return true;
    }

    private void FinishDraw()
    {
        try
        {
            Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width, ClientSize.Height);

           // GraphicsDevice.Present(sourceRectangle, null, Handle);
            GraphicsDevice.Present();
        }
        catch
        {
            // GULP
        }
    }

    private bool IsDeviceAvailable()
    {
        bool deviceNeedsReset;

        switch (graphicsDevice.GraphicsDeviceStatus)
        {
            case GraphicsDeviceStatus.Lost:
                return false;
            case GraphicsDeviceStatus.NotReset:
                deviceNeedsReset = true;
                break;
            default:
                deviceNeedsReset = (ClientSize.Width > parameters.BackBufferWidth) || (ClientSize.Height > parameters.BackBufferHeight);
                break;
        }

        if (deviceNeedsReset)
        {
            try
            {
                ResetDevice(ClientSize.Width, ClientSize.Height);
            }
            catch
            {
                return false;
            }
        }

        return true;
    }

    protected override void OnPaintBackground(PaintEventArgs p) { }

    public event EventHandler<EventArgs> DeviceCreated;
    public event EventHandler<EventArgs> DeviceDisposing;
    public event EventHandler<EventArgs> DeviceReset;
    public event EventHandler<EventArgs> DeviceResetting;

    protected override void Dispose(bool disposing)
    {
        if (graphicsDevice != null)
        {
            if (DeviceDisposing != null)
                DeviceDisposing(this, EventArgs.Empty);

            graphicsDevice.Dispose();
        }

        graphicsDevice = null;

        base.Dispose(disposing);
    }

    public void ResetDevice(int width, int height)
    {
        if (DeviceResetting != null)
            DeviceResetting(this, EventArgs.Empty);

        parameters.BackBufferWidth = Math.Max(parameters.BackBufferWidth, width);
        parameters.BackBufferHeight = Math.Max(parameters.BackBufferHeight, height);

        graphicsDevice.Reset(parameters);
        CreateSwapChainRenderTarget();
        if (DeviceReset != null)
            DeviceReset(this, EventArgs.Empty);
    }
   public void CreateSwapChainRenderTarget()
    {
       target = new SwapChainRenderTarget(graphicsDevice, this.Handle, ClientSize.Width, ClientSize.Height);
       
    }
}

Looks good. Make sure you don’t call SetRenderTarget(null) anywhere in your code.
Here’s what I use. more or less same thing.

#region File Description
//-----------------------------------------------------------------------------
// GraphicsDeviceControl.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace XnaHosting
{
    // System.Drawing and the XNA Framework both define Color and Rectangle
    // types. To avoid conflicts, we specify exactly which ones to use.
    using Color = System.Drawing.Color;
    using Rectangle = Microsoft.Xna.Framework.Rectangle;
    using Microsoft.Xna.Framework;


    /// <summary>
    /// Custom control uses the XNA Framework GraphicsDevice to render onto
    /// a Windows Form. Derived classes can override the Initialize and Draw
    /// methods to add their own drawing code.
    /// </summary>
    abstract public class GraphicsDeviceControl : Control
    {
        #region Fields

        // However many GraphicsDeviceControl instances you have, they all share
        // the same underlying GraphicsDevice, managed by this helper service.
        GraphicsDeviceService graphicsDeviceService;

        SwapChainRenderTarget _renderTarget;
        
        #endregion

        #region Properties


        /// <summary>
        /// Gets a GraphicsDevice that can be used to draw onto this control.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get { return graphicsDeviceService.GraphicsDevice; }
        }

        public RenderTarget2D DefaultRenderTarget { get { return _renderTarget; } }


        /// <summary>
        /// Gets an IServiceProvider containing our IGraphicsDeviceService.
        /// This can be used with components such as the ContentManager,
        /// which use this service to look up the GraphicsDevice.
        /// </summary>
        public ServiceContainer Services
        {
            get { return services; }
        }

        ServiceContainer services = new ServiceContainer();
        

        #endregion

        #region Initialization

        public GraphicsDeviceControl(): base()
        {
        }

        /// <summary>
        /// Initializes the control.
        /// </summary>
        protected override void OnCreateControl()
        {
            // Don't initialize the graphics device if we are running in the designer.
            if (!DesignMode)
            {
                graphicsDeviceService = GraphicsDeviceService.AddRef(Handle,
                                                                     ClientSize.Width,
                                                                     ClientSize.Height);

                _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);

                // Register the service, so components like ContentManager can find it.
                //services.AddService<IGraphicsDeviceService>(graphicsDeviceService);

                // Give derived classes a chance to initialize themselves.
                Initialize();

                //Set the XNA mouse handing to use this window
                //Mouse.WindowHandle = Handle;
                
                return;
            }

            base.OnCreateControl();
        }


        /// <summary>
        /// Disposes the control.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (graphicsDeviceService != null)
            {
                graphicsDeviceService.Release(disposing);
                graphicsDeviceService = null;
            }

            if (_renderTarget != null)
            {
                _renderTarget.Dispose();
                _renderTarget = null;
            }


            base.Dispose(disposing);
        }


        #endregion
              
        #region Paint
  
        /// <summary>
        /// Redraws the control in response to a WinForms paint message.
        /// </summary>        
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                //call drawing                     
                string beginDrawError = BeginDraw();
                if (string.IsNullOrEmpty(beginDrawError))
                {
                    // Draw the control using the GraphicsDevice.                    
                    Draw();
                    OnAfterDraw(EventArgs.Empty);
                    EndDraw();
                }
                else
                {
                    // If BeginDraw failed, show an error message using System.Drawing.
                    PaintUsingSystemDrawing(e.Graphics, beginDrawError);
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.StackTrace, ex.Message,MessageBoxButtons.OK,MessageBoxIcon.Error);
                int t = 5;
            }
            return;
        }
        

        /// <summary>
        /// Attempts to begin drawing the control. Returns an error message string
        /// if this was not possible, which can happen if the graphics device is
        /// lost, or if we are running inside the Form designer.
        /// </summary>
        internal string BeginDraw()
        {
            // If we have no graphics device, we must be running in the designer.
            if (graphicsDeviceService == null)
            {
                return Text + "\n\n" + GetType();
            }

            // Make sure the graphics device is big enough, and is not lost.
            string deviceResetError = HandleDeviceReset();

            if (!string.IsNullOrEmpty(deviceResetError))
            {
                return deviceResetError;
            }

            GraphicsDevice.SetRenderTarget(_renderTarget);

            // Many GraphicsDeviceControl instances can be sharing the same
            // GraphicsDevice. The device backbuffer will be resized to fit the
            // largest of these controls. But what if we are currently drawing
            // a smaller control? To avoid unwanted stretching, we set the
            // viewport to only use the top left portion of the full backbuffer.
            GraphicsDevice.Viewport = this.Viewport;

            return null;
        }

        public Viewport Viewport { get { return new Viewport(0, 0, ClientSize.Width, ClientSize.Height); } }


        /// <summary>
        /// Ends drawing the control. This is called after derived classes
        /// have finished their Draw method, and is responsible for presenting
        /// the finished image onto the screen, using the appropriate WinForms
        /// control handle to make sure it shows up in the right place.
        /// </summary>
        internal void EndDraw()
        {
            try
            {
                Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width,
                                                                ClientSize.Height);
                _renderTarget.Present();
            }
            catch
            {
                // Present might throw if the device became lost while we were
                // drawing. The lost device will be handled by the next BeginDraw,
                // so we just swallow the exception.
            }
        }


        /// <summary>
        /// Helper used by BeginDraw. This checks the graphics device status,
        /// making sure it is big enough for drawing the current control, and
        /// that the device is not lost. Returns an error string if the device
        /// could not be reset.
        /// </summary>
        string HandleDeviceReset()
        {
            bool deviceNeedsReset = false;

            switch (GraphicsDevice.GraphicsDeviceStatus)
            {
                case GraphicsDeviceStatus.Lost:
                    // If the graphics device is lost, we cannot use it at all.
                    return "Graphics device lost";

                case GraphicsDeviceStatus.NotReset:
                    // If device is in the not-reset state, we should try to reset it.
                    deviceNeedsReset = true;
                    break;

                default:
                    // If the device state is ok, check whether it is big enough.
                    PresentationParameters pp = GraphicsDevice.PresentationParameters;

                    deviceNeedsReset = (ClientSize.Width != pp.BackBufferWidth) ||
                                       (ClientSize.Height != pp.BackBufferHeight);
                    break;
            }

            // Do we need to reset the device?
            if (deviceNeedsReset)
            {
                try
                {
                    graphicsDeviceService.ResetDevice(_renderTarget.Width,
                                                      _renderTarget.Height);

                    //recreate window swapchain
                    _renderTarget.Dispose();
                    _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
                }
                catch (Exception e)
                {
                    return "Graphics device reset failed\n\n" + e;
                }
            }

            return null;
        }


        /// <summary>
        /// If we do not have a valid graphics device (for instance if the device
        /// is lost, or if we are running inside the Form designer), we must use
        /// regular System.Drawing method to display a status message.
        /// </summary>
        protected virtual void PaintUsingSystemDrawing(Graphics graphics, string text)
        {
            graphics.Clear(Color.CornflowerBlue);

            using (Brush brush = new SolidBrush(Color.Black))
            {
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;

                    graphics.DrawString(text, Font, brush, ClientRectangle, format);
                }
            }
        }

        /// <summary>
        /// Ignores WinForms paint-background messages. The default implementation
        /// would clear the control to the current background color, causing
        /// flickering when our OnPaint implementation then immediately draws some
        /// other color over the top using the XNA Framework GraphicsDevice.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }


        #endregion

        #region Abstract Methods

        /// <summary>
        /// Derived classes override this to initialize their drawing code.
        /// </summary>
        abstract protected void Initialize();
                
        /// <summary>
        /// Derived classes override this to draw themselves using the GraphicsDevice.
        /// </summary>
        abstract internal void Draw();
        
        #endregion


        private readonly object AfterDrawEventLock = new object();
        private EventHandler AfterDrawEvent;
        public event EventHandler AfterDraw
        {
            add { lock (AfterDrawEventLock) { AfterDrawEvent += value; } }
            remove { lock (AfterDrawEventLock) { AfterDrawEvent -= value; } }
        }
        protected virtual void OnAfterDraw(EventArgs e)
        {
            EventHandler handler = null;
            lock (AfterDrawEventLock)
            {
                handler = AfterDrawEvent;
                if (handler == null) return;
            }
            handler(this, e);
        }
    }
}

And here’s a screen shot with 5 controls.

2 Likes

Thanks a lot. I got it working now. Just in case anyone is interested I put your solution into a control that is not abstract and the Drawing code is triggered through an event. Not saying it is the prettiest solution, but for me it is more practical. In case someone is interested:

public class EditorControl : GraphicsDeviceControl
{
public event EventHandler OnInitialize;
public event EventHandler OnDraw;

    protected override void Initialize()
    {
        if (OnInitialize != null)
            OnInitialize(this, null);
    }

    internal override void Draw()
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        if (OnDraw != null)
            OnDraw(this, null);
    }
   
}

I’m a little confused because there is no GraphicsDeviceService in MonoGame 3.2, only an interface.
So I’m not sure what’s the meaning of GraphicsDeviceService.AddRef

I moved my Project from XNA to Monogame and have the same issues like Christian24, i changed the GraphicsDevice.Present to SwapChainRenderTarget and now it works. But in XNA my Editor runs smooth but now with Monogame it stutter, anyone have ideas to fix it?

using Color = System.Drawing.Color;
using IGameComponent = Engine.IGameComponent;
using Rectangle = Microsoft.Xna.Framework.Rectangle;

public class GameControl : Control
{

GraphicsDeviceService graphicsDeviceService;
SwapChainRenderTarget _renderTarget;


public GameControl()
{
    this.services = new ServiceContainer();

    this.content = new ContentManager(this.services);
    this.content.RootDirectory = ".";

    this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
    this.SetStyle(ControlStyles.UserPaint, true);

    this.GameLoopEnabled = true;
    this.TimeStep = 16.66666f;

    this.startTime = DateTime.Now;
}


private ServiceContainer services;
private ContentManager content;

private DateTime startTime;

private DateTime lastDraw;
private DateTime lastUpdate;

private Thread gameLoopThread;
private Thread eventThread;

private string errorMessage;

public IGameComponent Component { get; set; }

public bool GameLoopEnabled { get; set; }
public float TimeStep { get; set; }

public GraphicsDevice GraphicsDevice
{
    get
    {
        if (!this.DesignMode)
        {
            return this.graphicsDeviceService.GraphicsDevice;
        }
        return null;
    }
}

public ContentManager Content
{
    get { return this.content; }
}

public ServiceContainer Services
{
    get { return services; }
}

public Viewport Viewport { get { return new Viewport(0, 0, ClientSize.Width, ClientSize.Height); } }

public virtual void Initialize()
{

}

public virtual void LoadContent()
{
}

public virtual void UnloadContent()
{
}

public virtual void Draw(GameTime gameTime)
{
    if (Component != null)
    {
        Component.Draw(gameTime);
    }
}

public virtual void Update(GameTime gameTime)
{
    if (Component != null)
    {
        Component.Update(gameTime);
    }
}

internal string BeginDraw()
{
    if (graphicsDeviceService == null)
    {
        errorMessage = Messages.LostDevice;
    }
    string deviceResetError = handleDeviceReset();
   

    if (!string.IsNullOrEmpty(deviceResetError))
    {
        return deviceResetError;
    }

    GraphicsDevice.SetRenderTarget(_renderTarget);

    GraphicsDevice.Viewport = Viewport;

    return null;
}


public void EndDraw()
{
    try
    {
        Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width,
                                                      ClientSize.Height);
        _renderTarget.Present();
    }
    catch
    {
      
    }
}

public void Reset()
{
    try
    {
        this.graphicsDeviceService.ResetDevice(_renderTarget.Width, _renderTarget.Height);
        //recreate window swapchain
        _renderTarget.Dispose();
        _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
    }
    catch
    {
        this.errorMessage = Messages.ResetFailed;
    }
}

string handleDeviceReset()
{
    bool needsReset = false;
    switch (GraphicsDevice.GraphicsDeviceStatus)
    {
        case GraphicsDeviceStatus.Lost:
            return this.errorMessage = Messages.LostDevice;          
        case GraphicsDeviceStatus.NotReset:
            needsReset = true;
            break;

        default:
            PresentationParameters pp = GraphicsDevice.PresentationParameters;
            //needsReset = (ClientSize.Width > pp.BackBufferWidth) || (ClientSize.Height > pp.BackBufferHeight);
            needsReset = (ClientSize.Width != pp.BackBufferWidth) ||
           (ClientSize.Height != pp.BackBufferHeight);

            break;
    }
    if (needsReset)
    {
        try
        {
            graphicsDeviceService.ResetDevice(_renderTarget.Width,
                                           _renderTarget.Height);

            //recreate window swapchain
            _renderTarget.Dispose();
            _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
            
        }
        catch
        {
            return this.errorMessage = Messages.ResetFailed;
        }
    }
    return null;

}

private void paintDefault(Graphics graphics, string text)
{
    graphics.Clear(Color.DodgerBlue);

    using (Brush brush = new SolidBrush(Color.Black))
    {
        using (StringFormat format = new StringFormat())
        {
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            graphics.DrawString(text, Font, brush, ClientRectangle, format);
        }
    }
}

private void EngineGameLoop()
{
    Action loadContent = this.LoadContent;
    Action unloadContent = this.UnloadContent;

    this.lastUpdate = DateTime.Now;
    this.lastDraw = DateTime.Now;

    this.Invoke(loadContent);
    while (!this.IsDisposed)
    {
        try
        {
            DateTime drawStart = DateTime.Now;

            Action performDraw = () =>
            {
                this.BeginDraw();
                this.Draw(new GameTime(drawStart - this.startTime, drawStart - this.lastDraw));
                this.EndDraw();
            };
            this.Invoke(performDraw);
            this.lastDraw = drawStart;

            DateTime updateStart = DateTime.Now;

            Action performUpdate = () =>
            {
                this.Update(new GameTime(updateStart - this.startTime, updateStart - this.lastUpdate));
            };
            this.Invoke(performUpdate);
            this.lastUpdate = updateStart;

            TimeSpan elapsed = DateTime.Now - drawStart;
            if (elapsed.TotalMilliseconds >= this.TimeStep) continue;

            Thread.Sleep(TimeSpan.FromMilliseconds(this.TimeStep) - elapsed);
        }
        catch
        {
        }
    }
    this.Invoke(unloadContent);
}
protected override void OnCreateControl()
{
    if (!this.DesignMode)
    {
        this.graphicsDeviceService = GraphicsDeviceService.AddReference(
            Handle,
            ClientSize.Width,
            ClientSize.Height);

        _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);

        this.graphicsDeviceService.DeviceReset += new EventHandler<EventArgs>(onDeviceReset);
        this.services.AddService<IGraphicsDeviceService>(graphicsDeviceService);

        if (this.GameLoopEnabled)
        {
            this.gameLoopThread = new Thread(this.EngineGameLoop);
            this.gameLoopThread.IsBackground = true;
            this.gameLoopThread.Priority = ThreadPriority.Normal;

            this.gameLoopThread.Start();
        }
        else
        {
            this.LoadContent();
        }

    }
    base.OnCreateControl();
}

protected override void Dispose(bool disposing)
{
    if (this.graphicsDeviceService != null)
    {
        this.graphicsDeviceService.Release(disposing);
        this.graphicsDeviceService = null;

        if (this.gameLoopThread != null && this.gameLoopThread.IsAlive)
        {
            this.gameLoopThread.Abort();

        }
        if (_renderTarget != null)
        {
            _renderTarget.Dispose();
            _renderTarget = null;
        }

    }
    base.Dispose(disposing);
}

protected override void OnPaintBackground(PaintEventArgs e)
{
    if (this.DesignMode)
    {
        e.Graphics.Clear(Color.CornflowerBlue);
    }
    else
    {
        if (!this.GameLoopEnabled && this.GraphicsDevice != null)
        {
            GameTime gameTime = new GameTime(TimeSpan.Zero, TimeSpan.Zero);

            this.BeginDraw();
            {
                this.Draw(gameTime);
            }
            this.EndDraw();
        }
    }
}

private void onDeviceReset(object sender, EventArgs e)
{
    this.Initialize();
    this.errorMessage = string.Empty;
}

public static class Messages
{
    public static string DesignMode = "DESIGN MODE";
    public static string LostDevice = "LOST DEVICE";
    public static string ResetFailed = "RESET FAILED";
}

}

Here’s an updated version

#region File Description
//-----------------------------------------------------------------------------
// GraphicsDeviceControl.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Graphics;

namespace XnaHosting
{
    // System.Drawing and the XNA Framework both define Color and Rectangle
    // types. To avoid conflicts, we specify exactly which ones to use.
    using Color = System.Drawing.Color;
    using Rectangle = Microsoft.Xna.Framework.Rectangle;


    /// <summary>
    /// Custom control uses the XNA Framework GraphicsDevice to render onto
    /// a Windows Form. Derived classes can override the Initialize and Draw
    /// methods to add their own drawing code.
    /// </summary>
    abstract public class GraphicsDeviceControl : Control
    {
        // However many GraphicsDeviceControl instances you have, they all share
        // the same underlying GraphicsDevice, managed by this helper service.
        GraphicsDeviceService graphicsDeviceService;

        SwapChainRenderTarget _renderTarget;
        
        /// <summary>
        /// Gets a GraphicsDevice that can be used to draw onto this control.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get { return graphicsDeviceService.GraphicsDevice; }
        }

        public RenderTarget2D DefaultRenderTarget { get { return _renderTarget; } }


        /// <summary>
        /// Gets an IServiceProvider containing our IGraphicsDeviceService.
        /// This can be used with components such as the ContentManager,
        /// which use this service to look up the GraphicsDevice.
        /// </summary>
        public ServiceContainer Services
        {
            get { return services; }
        }

        ServiceContainer services = new ServiceContainer();
        
        public GraphicsDeviceControl(): base()
        {
        }

        /// <summary>
        /// Initializes the control.
        /// </summary>
        protected override void OnCreateControl()
        {
            // Don't initialize the graphics device if we are running in the designer.
            if (!DesignMode)
            {   
                graphicsDeviceService = GraphicsDeviceService.AddRef(Handle,
                                                                     ClientSize.Width,
                                                                     ClientSize.Height);

                int w = Math.Max(ClientSize.Width, 1);
                int h = Math.Max(ClientSize.Height,1);
                _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, w, h);

                // SetKeyboardInput(true);

                // Register the service, so components like ContentManager can find it.
                //services.AddService<IGraphicsDeviceService>(graphicsDeviceService);

                // Give derived classes a chance to initialize themselves.
                Initialize();

                //Set the XNA mouse handing to use this window
                //Mouse.WindowHandle = Handle;
                
                return;
            }

            base.OnCreateControl();
        }

        public void SetKeyboardInput(bool enable)
        {
            var keyboardType = typeof(Microsoft.Xna.Framework.Input.Keyboard);
            var methodInfo = keyboardType.GetMethod("SetActive", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
            methodInfo.Invoke(null, new object[] { enable });
        }
        

        /// <summary>
        /// Disposes the control.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (graphicsDeviceService != null)
            {
                graphicsDeviceService.Release(disposing);
                graphicsDeviceService = null;
            }

            if (_renderTarget != null)
            {
                _renderTarget.Dispose();
                _renderTarget = null;
            }

            base.Dispose(disposing);
        }


        /// <summary>
        /// Redraws the control in response to a WinForms paint message.
        /// </summary>        
        protected override void OnPaint(PaintEventArgs e)
        {
            // If we have no graphics device, we must be running in the designer.
            if (graphicsDeviceService == null)
            {
                PaintUsingSystemDrawing(e.Graphics, Text + "\n\n" + GetType());
                return;
            }

            try
            {
                //call drawing                     
                BeginDraw();
                // Draw the control using the GraphicsDevice.                    
                OnDraw(EventArgs.Empty);
                EndDraw();
            }
            catch (Exception ex)
            {
                PaintUsingSystemDrawing(e.Graphics, ex.Message + "\n\n" + ex.StackTrace);
            }
            return;
        }


        /// <summary>
        /// Attempts to begin drawing the control. Returns an error message string
        /// if this was not possible, which can happen if the graphics device is
        /// lost, or if we are running inside the Form designer.
        /// </summary>
        internal void BeginDraw()
        {
            // Make sure the graphics device is big enough, and is not lost.
            HandleDeviceReset();

            GraphicsDevice.SetRenderTarget(_renderTarget);

            // Many GraphicsDeviceControl instances can be sharing the same
            // GraphicsDevice. The device backbuffer will be resized to fit the
            // largest of these controls. But what if we are currently drawing
            // a smaller control? To avoid unwanted stretching, we set the
            // viewport to only use the top left portion of the full backbuffer.
            if (this.Viewport.Width == 0 || this.Viewport.Height == 0)
                throw new Exception("Viewport size cannot be Zero.");
            GraphicsDevice.Viewport = this.Viewport;

            return;
        }

        public Viewport Viewport 
        { 
            get 
            {
                int w = Math.Max(ClientSize.Width, 1);
                int h = Math.Max(ClientSize.Height, 1);
                return new Viewport(0, 0, w, h);
            } 
        }


        /// <summary>
        /// Ends drawing the control. This is called after derived classes
        /// have finished their Draw method, and is responsible for presenting
        /// the finished image onto the screen, using the appropriate WinForms
        /// control handle to make sure it shows up in the right place.
        /// </summary>
        internal void EndDraw()
        {
            try
            {
                Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width, ClientSize.Height);

                GraphicsDevice.SetRenderTarget(null);
                _renderTarget.Present();
            }
            catch
            {
                // Present might throw if the device became lost while we were
                // drawing. The lost device will be handled by the next BeginDraw,
                // so we just swallow the exception.
            }
        }


        /// <summary>
        /// Helper used by BeginDraw. This checks the graphics device status,
        /// making sure it is big enough for drawing the current control, and
        /// that the device is not lost. Returns an error string if the device
        /// could not be reset.
        /// </summary>
        void HandleDeviceReset()
        {
            bool deviceNeedsReset = false;

            switch (GraphicsDevice.GraphicsDeviceStatus)
            {
                case GraphicsDeviceStatus.Lost:
                    // If the graphics device is lost, we cannot use it at all.
                    throw new Exception("Graphics device lost");

                case GraphicsDeviceStatus.NotReset:
                    // If device is in the not-reset state, we should try to reset it.
                    deviceNeedsReset = true;
                    break;

                default:
                    // If the device state is ok, check whether it is big enough.                    
                    int w = Math.Max(ClientSize.Width, 1);
                    int h = Math.Max(ClientSize.Height, 1);
                    deviceNeedsReset = (w != _renderTarget.Width) ||
                                       (h != _renderTarget.Height);
                    break;
            }

            // Do we need to reset the device?
            if (deviceNeedsReset)
            {
                try
                {
                    int w = Math.Max(ClientSize.Width, 1);
                    int h = Math.Max(ClientSize.Height, 1);
                    graphicsDeviceService.ResetDevice(w, h);

                    //recreate window swapchain
                    _renderTarget.Dispose();
                    _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, w, h);
                }
                catch (Exception e)
                {
                    throw new Exception("Graphics device reset failed\n\n", e);
                }
            }

            return;
        }

        protected void ResetSwapChainRenderTarget()
        {
            if (_renderTarget != null)
                _renderTarget.Dispose();
            _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
        }


        /// <summary>
        /// If we do not have a valid graphics device (for instance if the device
        /// is lost, or if we are running inside the Form designer), we must use
        /// regular System.Drawing method to display a status message.
        /// </summary>
        protected virtual void PaintUsingSystemDrawing(Graphics graphics, string text)
        {
            graphics.Clear(Color.Black);

            using (Brush brush = new SolidBrush(Color.White))
            {
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = StringAlignment.Near;
                    format.LineAlignment = StringAlignment.Near;

                    graphics.DrawString(text, Font, brush, ClientRectangle, format);
                }
            }
        }

        /// <summary>
        /// Ignores WinForms paint-background messages. The default implementation
        /// would clear the control to the current background color, causing
        /// flickering when our OnPaint implementation then immediately draws some
        /// other color over the top using the XNA Framework GraphicsDevice.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }

        /// <summary>
        /// Derived classes override this to initialize their drawing code.
        /// </summary>
        abstract protected void Initialize();
                
        public event EventHandler Draw;
        
        /// <summary>
        /// Derived classes override this to draw themselves using the GraphicsDevice.
        /// </summary>
        protected virtual void OnDraw(EventArgs e)
        {
            EventHandler handler = Draw;
            if (handler != null)
                handler(this, e);
        }

    }
}
#region File Description
//-----------------------------------------------------------------------------
// GraphicsDeviceService.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework.Graphics;
#endregion

// The IGraphicsDeviceService interface requires a DeviceCreated event, but we
// always just create the device inside our constructor, so we have no place to
// raise that event. The C# compiler warns us that the event is never used, but
// we don't care so we just disable this warning.
#pragma warning disable 67

namespace XnaHosting
{
    /// <summary>
    /// Helper class responsible for creating and managing the GraphicsDevice.
    /// All GraphicsDeviceControl instances share the same GraphicsDeviceService,
    /// so even though there can be many controls, there will only ever be a single
    /// underlying GraphicsDevice. This implements the standard IGraphicsDeviceService
    /// interface, which provides notification events for when the device is reset
    /// or disposed.
    /// </summary>
    class GraphicsDeviceService : IGraphicsDeviceService
    {
        #region Fields


        // Singleton device service instance.
        static GraphicsDeviceService singletonInstance;


        // Keep track of how many controls are sharing the singletonInstance.
        static int referenceCount;


        #endregion


        /// <summary>
        /// Constructor is private, because this is a singleton class:
        /// client controls should use the public AddRef method instead.
        /// </summary>
        GraphicsDeviceService(IntPtr windowHandle, int width, int height)
        {
            parameters = new PresentationParameters();

            parameters.BackBufferWidth = Math.Max(width, 1);
            parameters.BackBufferHeight = Math.Max(height, 1);
            parameters.BackBufferFormat = SurfaceFormat.Color;
            parameters.DepthStencilFormat = DepthFormat.Depth24Stencil8;
            parameters.DeviceWindowHandle = windowHandle;
            parameters.PresentationInterval = PresentInterval.Immediate;
            parameters.IsFullScreen = false;
            
            graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
#if DEFERRED
                                                GraphicsProfile.HiDef,
#else
                                                GraphicsProfile.Reach,
#endif                                          
                                                parameters);
            return;
        }
        
        /// <summary>
        /// Gets a reference to the singleton instance.
        /// </summary>
        public static GraphicsDeviceService AddRef(IntPtr windowHandle,
                                                   int width, int height)
        {
            // Increment the "how many controls sharing the device" reference count.
            if (Interlocked.Increment(ref referenceCount) == 1)
            {
                // If this is the first control to start using the
                // device, we must create the singleton instance.
                singletonInstance = new GraphicsDeviceService(windowHandle,
                                                              width, height);
            }

            return singletonInstance;
        }


        /// <summary>
        /// Releases a reference to the singleton instance.
        /// </summary>
        public void Release(bool disposing)
        {
            // Decrement the "how many controls sharing the device" reference count.
            if (Interlocked.Decrement(ref referenceCount) == 0)
            {
                // If this is the last control to finish using the
                // device, we should dispose the singleton instance.
                if (disposing)
                {
                    if (DeviceDisposing != null)
                        DeviceDisposing(this, EventArgs.Empty);

                    graphicsDevice.Dispose();
                }

                graphicsDevice = null;
            }
        }

        
        /// <summary>
        /// Resets the graphics device to whichever is bigger out of the specified
        /// resolution or its current size. This behavior means the device will
        /// demand-grow to the largest of all its GraphicsDeviceControl clients.
        /// </summary>
        public void ResetDevice(int width, int height)
        {
            if (DeviceResetting != null)
                DeviceResetting(this, EventArgs.Empty);

            parameters.BackBufferWidth = Math.Max(parameters.BackBufferWidth, width);
            parameters.BackBufferHeight = Math.Max(parameters.BackBufferHeight, height);

            graphicsDevice.Reset(parameters);

            if (DeviceReset != null)
                DeviceReset(this, EventArgs.Empty);
        }

        
        /// <summary>
        /// Gets the current graphics device.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get { return graphicsDevice; }
        }

        GraphicsDevice graphicsDevice;


        // Store the current device settings.
        PresentationParameters parameters;


        // IGraphicsDeviceService events.
        public event EventHandler<EventArgs> DeviceCreated;
        public event EventHandler<EventArgs> DeviceDisposing;
        public event EventHandler<EventArgs> DeviceReset;
        public event EventHandler<EventArgs> DeviceResetting;
    }
}
#region File Description
//-----------------------------------------------------------------------------
// ServiceContainer.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
#endregion

namespace XnaHosting
{
    /// <summary>
    /// Container class implements the IServiceProvider interface. This is used
    /// to pass shared services between different components, for instance the
    /// ContentManager uses it to locate the IGraphicsDeviceService implementation.
    /// </summary>
    public class ServiceContainer : IServiceProvider
    {
        Dictionary<Type, object> services = new Dictionary<Type, object>();


        /// <summary>
        /// Adds a new service to the collection.
        /// </summary>
        public void AddService<T>(T service)
        {
            services.Add(typeof(T), service);
        }


        /// <summary>
        /// Looks up the specified service.
        /// </summary>
        public object GetService(Type serviceType)
        {
            object service;

            services.TryGetValue(serviceType, out service);

            return service;
        }
    }
}

How can I use a Rendertarget inside the control with this?
Just getting a black screen. Because the Begin and End setting a render target.

EDIT: Well I have a solution but don’t know if it’s the best approach.
Im rendering my Rendertarget first then calling the BeginDraw() from the control manually drawing everything and calling Endraw().

I removed BeginDraw and EndDraw from the OnPaint event.

Also Added a working GameTime if someone is interested.

#region File Description
//-----------------------------------------------------------------------------
// GraphicsDeviceControl.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Diagnostics;

namespace XnaHosting
{

    // System.Drawing and the XNA Framework both define Color and Rectangle
    // types. To avoid conflicts, we specify exactly which ones to use.
    using Color = System.Drawing.Color;
    using Rectangle = Microsoft.Xna.Framework.Rectangle;


    /// <summary>
    /// Custom control uses the XNA Framework GraphicsDevice to render onto
    /// a Windows Form. Derived classes can override the Initialize and Draw
    /// methods to add their own drawing code.
    /// </summary>
    abstract public class GraphicsDeviceControl : Control
    {
        TimeSpan elapsed;
        Stopwatch fakeGameTime;
        GameTime gameTime;

        // However many GraphicsDeviceControl instances you have, they all share
        // the same underlying GraphicsDevice, managed by this helper service.
        GraphicsDeviceService graphicsDeviceService;

        SwapChainRenderTarget _renderTarget;
        
        /// <summary>
        /// Gets a GraphicsDevice that can be used to draw onto this control.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get { return graphicsDeviceService.GraphicsDevice; }
        }

        /// <summary>
        /// Gets an IServiceProvider containing our IGraphicsDeviceService.
        /// This can be used with components such as the ContentManager,
        /// which use this service to look up the GraphicsDevice.
        /// </summary>
        public ServiceContainer Services
        {
            get { return services; }
        }

        ServiceContainer services = new ServiceContainer();
        
        public GraphicsDeviceControl(): base()
        {
        }

        /// <summary>
        /// Initializes the control.
        /// </summary>
        protected override void OnCreateControl()
        {
            // Don't initialize the graphics device if we are running in the designer.
            if (!DesignMode)
            {   
                graphicsDeviceService = GraphicsDeviceService.AddRef(Handle,
                                                                     ClientSize.Width,
                                                                     ClientSize.Height);

                int w = Math.Max(ClientSize.Width, 1);
                int h = Math.Max(ClientSize.Height,1);
                _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, w, h);

                // SetKeyboardInput(true);

                // Register the service, so components like ContentManager can find it.
                //services.AddService<IGraphicsDeviceService>(graphicsDeviceService);

                // Give derived classes a chance to initialize themselves.
                Initialize();

                //Set the XNA mouse handing to use this window
                //Mouse.WindowHandle = Handle;

                fakeGameTime = new Stopwatch();
                fakeGameTime.Start();

                return;
            }

            base.OnCreateControl();
        }

        public void SetKeyboardInput(bool enable)
        {
            var keyboardType = typeof(Microsoft.Xna.Framework.Input.Keyboard);
            var methodInfo = keyboardType.GetMethod("SetActive", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
            methodInfo.Invoke(null, new object[] { enable });
        }
        

        /// <summary>
        /// Disposes the control.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (graphicsDeviceService != null)
            {
                graphicsDeviceService.Release(disposing);
                graphicsDeviceService = null;
            }

            if (_renderTarget != null)
            {
                _renderTarget.Dispose();
                _renderTarget = null;
            }

            base.Dispose(disposing);
        }


        /// <summary>
        /// Redraws the control in response to a WinForms paint message.
        /// </summary>        
        protected override void OnPaint(PaintEventArgs e)
        {
            // If we have no graphics device, we must be running in the designer.
            if (graphicsDeviceService == null)
            {
                PaintUsingSystemDrawing(e.Graphics, Text + "\n\n" + GetType());
                return;
            }

            try
            {
                //call drawing                     
                // Draw the control using the GraphicsDevice.                    
                OnDraw(EventArgs.Empty);
            }
            catch (Exception ex)
            {
                PaintUsingSystemDrawing(e.Graphics, ex.Message + "\n\n" + ex.StackTrace);
            }
            return;
        }


        /// <summary>
        /// Attempts to begin drawing the control. Returns an error message string
        /// if this was not possible, which can happen if the graphics device is
        /// lost, or if we are running inside the Form designer.
        /// </summary>
        public virtual void BeginDraw()
        {
            // Make sure the graphics device is big enough, and is not lost.
            HandleDeviceReset();

            GraphicsDevice.SetRenderTarget(_renderTarget);

            // Many GraphicsDeviceControl instances can be sharing the same
            // GraphicsDevice. The device backbuffer will be resized to fit the
            // largest of these controls. But what if we are currently drawing
            // a smaller control? To avoid unwanted stretching, we set the
            // viewport to only use the top left portion of the full backbuffer.
            if (this.Viewport.Width == 0 || this.Viewport.Height == 0)
                throw new Exception("Viewport size cannot be Zero.");
            GraphicsDevice.Viewport = this.Viewport;

            return;
        }

        public Viewport Viewport 
        { 
            get 
            {
                int w = Math.Max(ClientSize.Width, 1);
                int h = Math.Max(ClientSize.Height, 1);
                return new Viewport(0, 0, w, h);
            } 
        }


        /// <summary>
        /// Ends drawing the control. This is called after derived classes
        /// have finished their Draw method, and is responsible for presenting
        /// the finished image onto the screen, using the appropriate WinForms
        /// control handle to make sure it shows up in the right place.
        /// </summary>
        public virtual void EndDraw()
        {
            try
            {
                Rectangle sourceRectangle = new Rectangle(0, 0, ClientSize.Width, ClientSize.Height);
                GraphicsDevice.SetRenderTarget(null);

                _renderTarget.Present();
            }
            catch
            {
                // Present might throw if the device became lost while we were
                // drawing. The lost device will be handled by the next BeginDraw,
                // so we just swallow the exception.
            }
        }


        /// <summary>
        /// Helper used by BeginDraw. This checks the graphics device status,
        /// making sure it is big enough for drawing the current control, and
        /// that the device is not lost. Returns an error string if the device
        /// could not be reset.
        /// </summary>
        void HandleDeviceReset()
        {
            bool deviceNeedsReset = false;

            switch (GraphicsDevice.GraphicsDeviceStatus)
            {
                case GraphicsDeviceStatus.Lost:
                    // If the graphics device is lost, we cannot use it at all.
                    throw new Exception("Graphics device lost");

                case GraphicsDeviceStatus.NotReset:
                    // If device is in the not-reset state, we should try to reset it.
                    deviceNeedsReset = true;
                    break;

                default:
                    // If the device state is ok, check whether it is big enough.                    
                    int w = Math.Max(ClientSize.Width, 1);
                    int h = Math.Max(ClientSize.Height, 1);
                    deviceNeedsReset = (w != _renderTarget.Width) ||
                                       (h != _renderTarget.Height);
                    break;
            }

            // Do we need to reset the device?
            if (deviceNeedsReset)
            {
                try
                {
                    int w = Math.Max(ClientSize.Width, 1);
                    int h = Math.Max(ClientSize.Height, 1);
                    graphicsDeviceService.ResetDevice(w, h);

                    //recreate window swapchain
                    _renderTarget.Dispose();
                    _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, w, h);
                }
                catch (Exception e)
                {
                    throw new Exception("Graphics device reset failed\n\n", e);
                }
            }

            return;
        }

        protected void ResetSwapChainRenderTarget()
        {
            if (_renderTarget != null)
                _renderTarget.Dispose();
            _renderTarget = new SwapChainRenderTarget(GraphicsDevice, Handle, ClientSize.Width, ClientSize.Height);
        }


        /// <summary>
        /// If we do not have a valid graphics device (for instance if the device
        /// is lost, or if we are running inside the Form designer), we must use
        /// regular System.Drawing method to display a status message.
        /// </summary>
        protected virtual void PaintUsingSystemDrawing(Graphics graphics, string text)
        {
            graphics.Clear(Color.Black);

            using (Brush brush = new SolidBrush(Color.White))
            {
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = StringAlignment.Near;
                    format.LineAlignment = StringAlignment.Near;

                    graphics.DrawString(text, Font, brush, ClientRectangle, format);
                }
            }
        }

        /// <summary>
        /// Ignores WinForms paint-background messages. The default implementation
        /// would clear the control to the current background color, causing
        /// flickering when our OnPaint implementation then immediately draws some
        /// other color over the top using the XNA Framework GraphicsDevice.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }

        /// <summary>
        /// Derived classes override this to initialize their drawing code.
        /// </summary>
        abstract protected void Initialize();
                
        /// <summary>
        /// Derived classes override this to draw themselves using the GraphicsDevice.
        /// </summary>
        protected virtual void OnDraw(EventArgs e)
        {
            gameTime = new GameTime(fakeGameTime.Elapsed, fakeGameTime.Elapsed - elapsed);
            elapsed = fakeGameTime.Elapsed;

            Update(gameTime);
            Draw(gameTime);
        }

        protected virtual void Update(GameTime gameTime) { }
        protected virtual void Draw(GameTime gameTime) {}
    }
}
1 Like