Jump to content

  • Log In with Google      Sign In   
  • Create Account

Mimicking ShowDialog


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 ta0soft   Members   -  Reputation: 107

Like
0Likes
Like

Posted 03 September 2012 - 11:12 AM

Hello everyone I have a pretty simple problem that I am having trouble with. I'm writing a GUI engine using SlimDX with custom controls like Buttons, Lists, Dialogs, etc.

My ZWindow class is basically just a Form with a custom ZControls property that allows me to add/remove controls. ZWindow handles all of the rendering and keyboard/mouse events for the child controls.

My ZDialog class is just a child control that can be moved/resized and has a titlebar and X (close) button. I have already added functions to Show, Hide, and Close the "dialog", now I am trying to implement a ShowDialog() method that works similar to System.Windows.Forms' ShowDialog. I hope that makes sense.

For example:

ZMessageBox mb = new ZMessageBox(ZWindow parent, string message);

if (mb.ShowDialog() == DialogResult.OK)

{

	// Perform action based on the DialogResult returned.

}



For this to work I need to wait until the user clicks a button or closes the dialog before ShowDialog() returns.

This is what I tried but it did not work as well as I had hoped:

public DialogResult ShowDialog()

{

	this.Show();



	while (this.Visible)

	{

		Application.DoEvents();

	}



	return this.DialogResult;

}



Does anyone know a better solution to this problem? Any help would be greatly appreciated. Thanks

Edited by ta0soft, 03 September 2012 - 11:26 AM.


Sponsor:

#2 SiCrane   Moderators   -  Reputation: 6785

Like
0Likes
Like

Posted 03 September 2012 - 11:28 AM

This is what I tried but it did not work as well as I had hoped:

Could you be more specific about what the problem is?

#3 ta0soft   Members   -  Reputation: 107

Like
0Likes
Like

Posted 03 September 2012 - 11:46 AM

I apologize. The problem is when the dialog is shown, it loops continuously and freezes my app even though DoEvents() is used and the Visible property is true, I'm not sure why. I also tried while (this.DialogResult == DialogResult.None) but had the same result.

I looked at the original Form.ShowDialog function in Reflector and no loops are used, so I think this is bad practice but I'm not sure what else to do.
The original function is hard to dissect, and since my dialogs are not actual windows I need a different approach.

Edited by ta0soft, 03 September 2012 - 12:27 PM.


#4 ta0soft   Members   -  Reputation: 107

Like
0Likes
Like

Posted 03 September 2012 - 03:01 PM

The only solution I can think of is using an OnClosing event instead and using Show() to show the dialog, but that would require handing the event every time a dialog is created.


p_MessageBox = new ZMessageBox(parent, message);

p_MessageBox.Closing += new EventHandler(p_MessageBox_Closing);

p_MessageBox.Show();



private void p_MessageBox_Closing(object sender, EventArgs e)

{

    if (p_MessageBox.DialogResult == DialogResult.OK)

    {

	    // ...

    }

}



This method works but is not the preferred approach because it takes a lot more code to perform the same task.
I need a way to suspend ShowDialog() until the user presses ok or cancel (or the X button), while still allowing other code to be executed.

#5 krippy2k8   Members   -  Reputation: 629

Like
1Likes
Like

Posted 03 September 2012 - 08:00 PM

I looked at the original Form.ShowDialog function in Reflector and no loops are used, so I think this is bad practice but I'm not sure what else to do.


I'm pretty sure it does use a loop. If you drill deep enough you will find that it eventually executes a complete Windows message loop.

The only way you will be able to duplicate this in a DX application would be to continue to execute your main game loop within your ShowDialog method until the dialog is closed.

#6 ta0soft   Members   -  Reputation: 107

Like
1Likes
Like

Posted 04 September 2012 - 11:11 AM

Thanks krippy2k8 you are exactly right, and I figured out why the app appears to freeze inside the loop. I am using the Application.Idle event for my main loop, so obviously the application is not idle during the while loop, even when DoEvents() is used.

Here is my working code for future reference.

ZWindow:

public bool Idle

{

	get

	{

		NativeMethods.Message msg;

		return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);

	}

}



private void Application_Idle(object sender, EventArgs e)

{

	while (this.Idle) Render();

}



internal void Render()

{

	if (!p_Direct3D.Valid) p_Direct3D.ResetDevice();



	p_Direct3D.BeginRender(this.BackColor);



	foreach (ZControl control in p_Controls)

	{

		control.Render();

	}



	p_Direct3D.EndRender();

}



ZDialog:

public DialogResult ShowDialog()

{

	Show();



	while (p_DialogResult == DialogResult.None)

	{

		Application.DoEvents();

		ParentWindow.Render();

	}



	return p_DialogResult;

}



Thanks again!

Edited by ta0soft, 04 September 2012 - 11:17 AM.


#7 Postie   Members   -  Reputation: 593

Like
0Likes
Like

Posted 04 September 2012 - 09:32 PM

I faced the exact same situation when I implemented a MessageBox control for my current project (also using SlimDX).

I tried a few approaches but ended up creating a static method on my WindowManager class to show the Message Box as follows:

[source lang="csharp"]public static void MessageBox(MessageBoxSettings messageBoxSettings, EventHandler<DialogResultEventArgs> onCloseHandler){ var messageBoxControl = new MessageBoxControl("messageBox", messageBoxSettings); if (onCloseHandler != null) { messageBoxControl.OnClose += onCloseHandler; } ShowWindow(messageBoxControl);}[/source]

Unfortunately it means you can't have the stop... go, type behaviour that happens with a real message box, but I decided that it was an ok trade off, because I don't actually want the main thread to stop. The game engine still has to keep rendering and processing keypresses and the like, so it made sense to me that the code reflect how it is supposed to work, instead of having to put in a message loop that replicates what the main thread is already doing.
Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS