tksuoran's picture

Create hidden GameWindow

Project:The Open Toolkit library
Version:1.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:open
Description

I need to hack GameWindow.Run() if I want to create a GameWindow which is hidden during load time. I show a smooth progress bar using Forms at load time.

I managed to get GameWindow created hidden, and get it visible later. But the window does not show up top most, no matter what functions I call. I tried ShowWindow(), SetFocus(), BringWindowToTop(), SetForegroundWindow(), even SwitchToThisWindow(), on WinGLNative.Visible setter, but the GameWindow still remains behind Windows folder window where I click to start my app. I can make the window show on top using ExtendedWindowStyle.Topmost but that is not an option. Any ideas?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

#1

Are you creating the GameWindow in the same thread as your Form? This is not safe, because the WinForms message pump interferes with the GameWindow.

If you disable the Form, does the GameWindow appear correctly on top? If so, you know the cause. In this case, the simplest solution is to spawn the Form in a different AppDomain/Process (see ExampleBrowser.cs line 379).

tksuoran's picture

#2

No, I have a separate thread where I create the form and call Application.Run(form).

        private object syncFormCreated = new object();
        private System.Threading.Thread loadingThread;
        private void LoadingScreen()
        {
            LoadingForm form = new LoadingForm();
            form.Location = new System.Drawing.Point(
                System.Windows.Forms.Screen.GetWorkingArea(form).Width / 2 - form.Width / 2,
                System.Windows.Forms.Screen.GetWorkingArea(form).Height / 2 - form.Height / 2
            );
            form.BringToFront();
            this.form = form;
            lock(syncFormCreated)
            {
                System.Threading.Monitor.Pulse(syncFormCreated);
            }
            System.Windows.Forms.Application.Run(form);
        }
        protected void SpawnLoadingScreen()
        {
            loadingThread = new System.Threading.Thread(LoadingScreen);
            loadingThread.Start();
            lock(syncFormCreated)
            {
                System.Threading.Monitor.Wait(syncFormCreated);
            }
            lock(form.syncFormVisible)
            {
                System.Threading.Monitor.Wait(form.syncFormVisible);
            }
            Debug.WriteLine("Done");
        }
        public void Prepare()
        {
            SpawnLoadingScreen();
tksuoran's picture

#3

I can confirm that the showing on top issue goes away if I disable showing the form. However, as you can see from to code I posted, I do create and run the form in a separate thread. Is there anything else I could try?

the Fiddler's picture

#4

Try creating using different AppDomains for each toolkit. This is the only 100% safe approach, plus it allows you to unload the WinForms domain once you no longer need it (otherwise, it will remain loaded eating up resources even if you are not using it).

Creating an AppDomain is almost as easy as launching a thread.

(Note: most toolkits assume full control of the windowing system. It's generally not a good idea to mix different toolkits in the same process, e.g. GTK+ and Qt or WxWindows and GTK+ or, indeed, WinForms and OpenTK).

tksuoran's picture

#5

Hmm. I suppose I could create one visible GameWindow to show the progress bar, which is thrown away once loading is done, and another, "the real" GameWindow, which remains hidden while loading. Should this work? Do they need their own AppDomain or is separate thread sufficient?

the Fiddler's picture

#6

You can spawn multiple GameWindows in different threads, no problem.