[SOLVED] Monogame winforms

Okay. Do you know why I only get a black window inside my form?

Thanks in advance!

Hello. I have posted 2 libraries.

This is based on the Xna tutorial DIRECTLY PORTED to monogame.
https://github.com/ArchaicOokami/MonoGame.Framework.Control

This one is based on a modification to the above version.
https://github.com/ArchaicOokami/Microsoft.Xna.Framework.Control

In the Microsoft Xna Framework Control - based on the xna forms control example - You have to have 3 classes.

  • GraphicsControlDevice
  • GraphicsDeviceService
  • Service Container

When using this you will create a new class, inherit GraphicsDeviceControl(Which in turn is making a UserControl) and modify the draw function to perform your task. After having this ready and throwing it on a form, which requires a whole new control per window(even if they only slightly differ) as well as to call somewhere in the code to draw. This can be done by adding the draw code to Application.Idle, or by manually calling the draw within a main loop.

The current compiled edition in my git post is targetting .net 4.0 and uses MonoGame 3.4.

While using my modified library, MonoGame Framework Control all you need to do is put a GraphicsDeviceControl onto your form. Then add the Draw event from visual designer and add you code there. The clearcolor is done automatically before draw is called and can be set via code or visual designer as it is a property you can modify from the Properties window. In order to make this one draw all you have to do is set AutoDraw to true from the visual designer or set it to false and manually call the draw inside of a loop.

The current compiled edition in my git post is targetting .net 4.5 and uses MonoGame 3.5.

Both of these can also be found on Nuget by searching ArchaicSoft or the names they are listed as in the git aka -
MonoGame.Framework.Control
Microsoft.Xna.Framework.Control

PS: To anyone wondering why my random post, the person asking the question requested i post this here.

1 Like

Thank you! It’s finally working :smiley:

Hey Damien, I’ve had a few goes at getting your control to work for me, but unfortunately as I have virtually no Winforms experience, i’m getting stuck.

Any chance you could pop a super basic example up onto your GitHub?

I’ve got VS2015 Community, I’ve tried creating a new winforms application, getting OpenTK.GLControl and your MonoGame.Framework.Control from NuGet, but I’m unable to select a GraphicsDeviceControl from the toolbox to add to the form layout.

My goal is to try and update/replicate Gleed2D which I’ve used as a level editor in the past.

Any help (or a basic example) would be greatly appreciated!

@marksarcade Before you can select a custom control from the toolbox in winforms, you have to import the control to also be inside the toolbox using the “Choose Toolbox Item” dialog ( https://msdn.microsoft.com/en-us/library/ms165355(v=vs.100).aspx) . You have to add the reference to the .dll file from the packages folder (from NuGet) inside this dialog before you can use the control from the toolbox.

Thanks @MasterQuestMaster. I have tried that, but all I get is the OpenTK.GLControl control, not the GraphicsDeviceControl mentioned in the post above, which is why a bit confused. I can see in the Object Browser on the referenced Monogame.Framework.Control library, the GraphicsDeviceControl as well as the OpenTK.GLControl.

I dropped my project version back to 4.5 from 4.5.2, but that didn’t seem to help.

Really lost as to what I might be missing?

In that case, I don’t know what the problem is.

That’s a shame, thanks for the suggestions :slightly_smiling:

@Damien_James_Gibson Don’'t suppose you know what might be stopping me from adding the Monogame.Framework.Control GraphicsDeviceControl to my toolbox?

@marksarcade Did you create a class that inherit GraphicsDeviceControl or are you trying to add GraphicsDeviceControl itself? You have to create a class that inherit GraphicsDeviceControl, build the application and then the class should show up in the toolbox. I can give you an example later today if you still can’t get it working :slight_smile:

I tried that a few ways as well (both with the Monogame.Framework and the Microsoft.Xna.Framework version of the Control) and can’t seem to get any work :frowning:

A simple example would be REALLY appreciated! I’m stumped as to what i’m doing wrong!?!? :confused:

@marksarcade Okay, here’s an example on how I got it working: https://github.com/TS1997/MonogameInWinforms
Editor.cs is my control class. Let me know if you need more help :slight_smile:

Thanks @TS1997, that works. I was trying to use the NuGet package which I thought was the way to go, I guess I should have just tried downloading the code and creating the control myself!

Depends on which version of the control you were grabbing… if it was based on the Xna implementation you have to make a class that inherits the GraphicsDeviceControl in order to make a control appear in the toolbox… if you grabbed the Latest Control.DirectX version then you can use the render event on a GraphicsDeviceControl rather than having to inherit one to make a toolbox item.

Hi,

The links provided by @Damien_James_Gibson are dead,
and the solution proposed by @TS1997 only Draws when Winforms decides to Invalidate the Control.

I would need a solution that refresh the control at 30FPS or so.

Monogame + Winform seems kinda tricky, couldn’t find anything reliable…
Thanks for the help

Here is what I use in a WPF project. Same thing basically, I use a WinFormsHost for the rendering control.

in main window:

        Thread thread;

private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            // start update/render thread
            thread = new Thread(UpdateRenderThread);
            thread.Start();
        }

void UpdateRenderThread()
        {
			while (Application.Current != null) //stop when app exit
            {
                bool updated = this.mainViewModel.Tick();               
            }
        }

And the Tick() method is a Game loop

        Stopwatch stopWatch = Stopwatch.StartNew();
        readonly TimeSpan TargetElapsedTime = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / 60);
        readonly TimeSpan skipFrames = TimeSpan.FromTicks((TimeSpan.TicksPerSecond / 60) * 15);
        TimeSpan _prevFrameTime = TimeSpan.Zero;
        public GameTime GameTime = new GameTime();
        bool _isRunningSlowly = false;

 internal bool Tick()
        {
            bool skipDrawFrame = false;
            
            TimeSpan currentTime = stopWatch.Elapsed;
            TimeSpan elapsedTime = currentTime - _prevFrameTime;
            
            TimeSpan currFrameTime = _prevFrameTime + TargetElapsedTime;

            if (currentTime > currFrameTime)
            {
                skipDrawFrame = true;
            }
            
            if (currentTime < _prevFrameTime)
            {
                var sleepTime = _prevFrameTime - currentTime;
                System.Threading.Thread.Sleep(sleepTime);
                return false;
            }

            //too slow. skip ahead.
            while((currFrameTime + skipFrames) < currentTime)
            {
                currFrameTime = _prevFrameTime + skipFrames;
                _prevFrameTime = currFrameTime;
                return false;
            }

            // do update
            do
            {
                // run update on app thread.
                if (Application.Current == null) return false;
                Application.Current.Dispatcher.BeginInvoke(
                    System.Windows.Threading.DispatcherPriority.Send, new Action(() =>
                    {
                        this.GameTime = new GameTime(currFrameTime, TargetElapsedTime, _isRunningSlowly);
                        if (model.AetherEngine != null)
                            model.AetherEngine.Tick(GameTime);
                    })).Wait();

                //move to next frame
                _prevFrameTime = currFrameTime;
                currFrameTime = _prevFrameTime + TargetElapsedTime;
            } while (currFrameTime < currentTime);

            if (!skipDrawFrame)
            {
                // invalidate all rendering controls
                DocumentViewModel[] documents = new DocumentViewModel[Documents.Count];
                Documents.CopyTo(documents, 0);
                foreach (var document in documents)
                {
                    var documentViewModel = document as ProtonType.ViewModels.Base.DocumentViewModel;
                    if (documentViewModel!=null)
                        documentViewModel.editorControl.Invalidate();
                }
            }

Of course you have to rewrite some bits to fit to your project structure.
With the above I am getting smooth frames on multiple windows.

Are you using Gemini? That looks really useful!

1 Like

No, it’s been developed over the past years, but it still needs some work.

1 Like

That’s exactly the approach I’m working on right now.
This piece of code is going to be very useful, Thanks a lot.
I’ll publish the Winform version very soon.

@raizam Did you get anywhere getting this to work in winforms?

Also, if this can be done, or one were to use the wpf example above, can events be sent into the monogame? Such as drag dropping?

@TheGrovesy I remember ended up playing with Gemini as @Jjagg mentioned.

you can try to have a look there https://www.google.fr/search?q=xna+winforms&oq=xna+winform&aqs=chrome.0.0j69i57j0l4.3999j0j7&sourceid=chrome&ie=UTF-8#q=xna+winforms+github