WinForms XNA to MonoGame Game drawing to a picture box not drawing

We have a super outdated editor we’re trying to convert to MonoGame. It creates a Game instance and sets the PresentationParameters.DeviceWindowHandle to the IntPtr of the PictureBox. After that, it hides the game itself and allows the picture box to be the only presentation for it.

Mind you, the editor is extremely old but is “good enough” so we’re trying to minimize complete refactoring.

Here’s what it looks like in XNA

When switching to XNA, the picturebox isn’t rendering anything.
I removed the code that hides the game window to show that the game itself is rendering.

protected override void Initialize()
        {
            winform = (Forms.Form)Forms.Form.FromHandle(Window.Handle);
            winform.VisibleChanged += new EventHandler(Game1_VisibleChanged);
            //winform.Size = new System.Drawing.Size(10, 10);
            //winform.Hide();
            
            // resize backbuffer to MainForm's pictureBox
            drawSurface = MainForm.Instance.getHandle();
            graphics.PreparingDeviceSettings += graphics_PreparingDeviceSettings;
            resizebackbuffer(MainForm.Instance.pictureBox1.Width, MainForm.Instance.pictureBox1.Height);
       
            Editor.Instance.Initialize(winform);

            base.Initialize();
        }

void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
        {
            e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = drawSurface;
        }

public void resizebackbuffer(int width, int height)
        {
            graphics.PreferredBackBufferWidth = width;
            graphics.PreferredBackBufferHeight = height;
            graphics.ApplyChanges();
        }

 private void Game1_VisibleChanged(object sender, EventArgs e)
        {
             //winform.Hide();
            // winform.Size = new System.Drawing.Size(10, 10);
            // winform.Visible = false;
            
        }

protected override void Draw(GameTime gameTime)
        {
            float fps = 1 / (float)gameTime.ElapsedGameTime.TotalSeconds;
            MainForm.Instance.toolStripStatusLabel4.Text = "FPS: " + fps.ToString("#0.00");


            Editor.Instance.draw(spriteBatch);

            base.Draw(gameTime);

        }

I’ve managed to get this working just. It seems that whatever is attached to PreparingDeviceSettings only gets called between the constructor and the Initialize method.

Try moving this line into the Constructor instead:

graphics.PreparingDeviceSettings += graphics_PreparingDeviceSettings;

Also it seems you can set the DeviceWindowHandle to a different Form at any point by doing this instead (the DeviceWindowHandle won’t be updated on a Reset unless the MultiSampleCount is also changed as this forces a new swap chain to be created):

GraphicsDevice.PresentationParameters.DeviceWindowHandle = drawSurface;
GraphicsDevice.PresentationParameters.MultiSampleCount = (GraphicsDevice.PresentationParameters.MultiSampleCount == 2) ? 4 : 2;
GraphicsDevice.Reset(GraphicsDevice.PresentationParameters);

Hope that helps.

1 Like

Moving PreparingDeviceSettings to the constructor worked perfectly. Thanks a lot!

3 Likes