Forcing ShowDialog and DirectX to play nice

Started by
1 comment, last by gamezo 15 years, 12 months ago
Hey everyone, First of all, I've spent at least a day or so looking for a solution to this so if I've simply missed an obvious thing, please feel free to send me back to the search engines, but I don't think think is completely something really simple. My problem is with Form.ShowDialog and DirectX. The first time around, when I show a modal form with DirectX rendering to it, everything works fine, any subsequent attempts to Form.ShowDialog after closing the first showing of it will cause a GraphicsException at the Device.Present call. I'm thinking it has to do with losing and resetting the device, but I've tried catching each respective exception and just setting up "properly" for each condition, but neither seems to be what's truly happening. The only think I can surmise is that ShowDialog creates a new window each time and so has a new "handle" so the PresentationParameters need to be possibly reset to correct values, but then everything should be encapsulated in the same Form instance and so if the pointer is valid, then the whole thing should be still valid. Now keep in mind that calling Form.Show and Form.Hide works great, but I need a modal dialog in order to stop the "main" thread from counting. I know, it's not the ideal way to do that, but it's a team project and people are being stubborn so I must work around specific things. Any other ways you guys can propose in order to pause a main thread updating during my MDX form being up would be greatly appreciated. THANK YOU FOR ANY Help you can give me!!
Advertisement
If you need to re-use a Form without recreating it every time, try overriding DestroyHandle() to only call base.DestroyHandle() once Dispose is called. However, this is one of my pet-peeves about Windows Forms. The only two ways to sleep a thread while processing the message loop that I've found are:

- Application.Run(), and exiting with Application.ExitThread(). But this will close all open Forms no matter what, and you can't use it during a message callback.
- Form.ShowDialog(). However this (of course) opens up a window, and in your case DirectX doesn't seem to play well with other windows.

The easiest method is probably to import the Win32 GetMessage. However if you don't know about Win32, I've experimented with a hack that looks something like this:

class MessageLoopDialog : Form{	protected override CreateParams CreateParams	{		get		{			Visible = false; // Hack!			return base.CreateParams;		}	}	public void Wait()	{		ShowDialog();	}	private delegate void InvokeDelegate();	public void StopWaiting()	{		// Stop waiting in thread-safe way		BeginInvoke(new InvokeDelegate(delegate()		{			DialogResult = DialogResult.OK;		}));	}}


Setting Visible=false before CreateParams fools the Form into creating an invisible window, and then ShowDialog will act like a message pump. A Windows.Form.Timer can be used to wait a certain amount of time, or another thread can break it out. I have a lot of doubts whether this will work in the long term though.
hh10k THANK YOU!!!!

I actually do know Win32 quite a bit as I did C++ DX development before C#, but I didn't wanna mess with it too much as it seemed messy (well except I had to use it for checking if Application is still idle) and I knew there had to be a workaround I wasn't seeing. Overriding the DestroyHandle worked great. Exactly what I wanted/needed. Now I'm off to have the form actually reset everything each time it's opened. Again, THANK YOU!

This topic is closed to new replies.

Advertisement