3 forms Show and ShowDialog not working as expected, BUG? - c#

I am using Visual Studio 2010, C# .NET 4.0. I have 3 forms: Form1, Form2, Form3.
In Form1 I have a button to open Form2:
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
}
In Form2 I have a private Form3 variable always pointing to the same Form3:
private Form3 f = new Form3();
And a button to open it as a dialog:
private void button1_Click(object sender, EventArgs e)
{
f.ShowDialog();
}
In Form3 I just have a button to hide the form:
private void button1_Click(object sender, EventArgs e)
{
this.Hide();
}
The problem is that having the situation that Form2 is in front of Form1, and Form3 in front of Form2, when I click the button of Form3 to hide it, it not only hides itself but sends Form1 to the back of all of the other Windows.
This only happens when there is a window of another program (such as Windows Explorer) in the background of Form1. It seems like a bug. What do you think?

Yes, this cannot work properly by design. A dialog disables all of the windows that your program displays. So that it is modal. When you hide the dialog, there are no windows left that can get the focus. Windows is forced to find another window to give the focus to. That will be a window owned by another application. Your own windows will now hide behind it.
There are more side effects, the dialog will also close. Necessary because otherwise the user can never get back to your program anymore since all windows are disabled. This is all unsurprising behavior. Bug would be a strong word, but it would of course work better if it first re-enabled all windows before closing the dialog. But closing the dialog is already undesirable behavior.
Don't call Hide() for a dialog. Just set the DialogResult property to DialogResult.Cancel to achieve the exact same effect, minus the focus problem. You do have to reset it back to None if you want to display the dialog again. That's a real bug.

By the documentation. Form.Close method doesn't dispose forms shown by Form.ShowDialog method. Quote:
The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
So, maybe there are ways to return focus to your application (e.g. via Windows API). But it is much more convenient to call Form.Close manually on dialog windows.

Related

Multiple forms in the same window in C#

I'm interested in the way to make some sub-forms, like child forms (for example, helper form that shows when you click on a find button and want to search through the suppliers).
But I don't want it to create another "window" in the taskbar, but to be integrated in the main form.
I know about Show() and ShowDialog(), but it opens another window in the taskbar...
I tried with MDI and was able to make it, but I don't want to use MDI.
So, can someone provide some knowledge about some alternative?
I've seen examples of this in some programs, but I don't know how is this achieved. I'm pretty new to visual C#.
For your other form use the ShowInTaskbar property and set it to false
this.ShowInTaskbar = false;
Then you can either use Show() or ShowDialog()
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}

Different form will not load

I'm using c# to make a mobile 6 application. I created another windows form in the project. This is the form that I would like to load first. This is what have tried:
MainMenu gameMenu = new MainMenu();
private void MainForm_Load(object sender, EventArgs e)
{
this.Hide();
gameMenu.ShowDialog();
.....
}
When I run this the emulator comes up but it just stays as the default windows screen. And I don't get any of my forms.
GameMenu's parent is MainForm, which is now hidden, so the Dialog isn't going to be visible. You need to adjust your logic to do one of the following:
show the GameMenu first (i.e. Application.Run(new GameMenu))
Don't hide MainForm
Use gameMenu.Show() instead of ShowDialog()
You may need to get rid of this.Hide() or use gameMenu.Show() instead of gameMenu.ShowDialog() or you may need to do both.
If you have to use gameMenu.Show() instead of gameMenu.ShowDialog(), you may also want to do the following:
Subscribe to MainForm's GotFocus event and call gameMenu.Show() again whenever the other form gains focus unintentionally. Set MainForm's Enabled property to false while the gameMenu is shown if you want to prevent any accidental interaction with the MainForm while the gameMenu is supposed to be shown.

WinForms programming - Modal and Non-Modal forms problem

I have a problem with modality of the forms under C#.NET. Let's say I have main form #0 (see the image below). This form represents main application form, where user can perform various operations. However, from time to time, there is a need to open additional non-modal form to perform additional main application functionality supporting tasks. Let's say this is form #1 in the image. On this #1 form there might be opened few additional modal forms on top of each other (#2 form in the image), and at the end, there is a progress dialog showing a long operation progress and status, which might take from few minutes up to few hours. The problem is that the main form #0 is not responsive until you close all modal forms (#2 in the image). I need that the main form #0 would be operational in this situation. However, if you open a non-modal form in form #2, you can operate with both modal #2 form and newly created non modal form. I need the same behavior between the main form #0 and form #1 with all its child forms. Is it possible? Or am I doing something wrong? Maybe there is some kind of workaround, I really would not like to change all ShowDialog calls to Show...
Image http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png
Modal forms do exactly what "modal" means, they disable all other windows in the app. That's rather important, your program is in a somewhat perilous state. You've got a chunk of code that is waiting for the dialog to close. Really Bad Things could happen if those other windows were not disabled. Like the user could start the modal dialog again, now your code is nested twice. Or she could close the owner window of the dialog, now it suddenly disappears.
These are the exact kind of problems you'd run into if you call Application.DoEvents() inside a loop. Which is one way to get a form to behave modal without disabling other windows. For example:
Form2 mDialog;
private void button1_Click(object sender, EventArgs e) {
mDialog = new Form2();
mDialog.FormClosed += (o, ea) => mDialog = null;
mDialog.Show(this);
while (mDialog != null) Application.DoEvents();
}
This is dangerous.
It is certainly best to use modal forms the way they were designed to stay out of trouble. If you don't want a modal form then simply don't make it modal, use the Show() method. Subscribe to its FormClosing event to know that it is about to close:
private void button1_Click(object sender, EventArgs e) {
var frm = new Form2();
frm.FormClosing += new FormClosingEventHandler(frm_FormClosing);
frm.Show();
}
void frm_FormClosing(object sender, FormClosingEventArgs e) {
var frm = sender as Form2;
// Do something with <frm>
//...
}
The first thing that comes to mind would be something like this. You could disable form 1 when you launch form 2 and then have form 1 handle the closed event of the second form to re-enable itself. You would NOT open modal 2 using show dialog.
Now keep in mind, from a user perspective this is going to be quite cumbersome, you might look at doing a MDI application to get all windows inside of a single container.
Your main form will not be responsive until any modal dialogs that are in the same process space are closed. There is not work around for that.
It looks to me like you could use an MDI application setting the Form #0 IsMdiContainer property to true.
Then, you could do something alike:
public partial class Form0 {
public Form0 {
InitializeComponent();
this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened.
}
private void button1_Click(object sender, EventArgs e) {
Form1 newForm1 = new Form1();
newForm1.Parent = this;
newForm1.Show();
}
}
Using the ShowDialog() as you stated in your question will make all of the forms Modal = true.
By definition, a modal form is:
When a form is displayed modally, no input (keyboard or mouse click) can occur except to objects on the modal form. The program must hide or close a modal form (usually in response to some user action) before input to another form can occur. Forms that are displayed modally are typically used as dialog boxes in an application.
You can use this property [(Modal)] to determine whether a form that you have obtained from a method or property has been displayed modally.
So, a modal form shall be used only when you require immediate assistance/interaction from the user. Using modal forms otherwise makes believe that you're perhaps running into a wrong direction.
If you do not want your main form to be an MDI container, then perhaps using multithreading is one solution through a simple BackgroundWorker class is the key to what you want to achieve. Thus, it looks to me like a design smell...
What is it you want to do, apart of making your main form responsive, etc.
What is it you have to do?
Explaining what you have to do, we might be able to guide you altogether into the right, or at least perhaps better, direction.
Actually the answer is very simple. Try
newForm.showDialog();
This will open a new form, while the parent one is inaccessible.

C# Form Problem: new form losing control and randomly hiding

I'm encountering strange behavior with forms on a c# 3.5 app. On a button click, my form1 hides itself, creates a new form2, and shows form2. Form1 also contains the event method triggered when form2 closes. Here's the code inside Form1:
Form2 form2;
void button1_Click(object sender, EventArgs e)
{
this.Hide();
form2 = new form2();
form2.Show();
form2.FormClosed += new FormClosedEventHandler(form2_FormClosed);
}
void form2_FormClosed(object sender, FormClosedEventArgs e)
{
form2.Dispose();
form2 = null;
this.Show();
}
Now, my problem is that sometimes when I open form2 (hiding form1), or when I close form2 (showing form1), the new form will come up on the screen for a blink and then hide itself. It's still open and I can click it from the taskbar to show it again, but the window itself is sent behind any other open windows. It looks like it opens up but minimizes instantly.
This behavior occurs randomly. Sometimes forms will open up and hide without a problem, but sometimes they'll lose focus over another window. I've tried using focus(), activate(), and topmost but all have failed to prevent the sudden hiding.
Does anyone know why is this happening and how to fix it?
Thanks.
You hide your form too soon. For a brief moment, your app has no window that can contain the focus. That forces Windows to go hunting for another window to give the focus to, it will pick one from another application. That window will now be the foreground window, your second form will not get the focus and appear lower in the Z-order. The fix is simple:
void button1_Click(object sender, EventArgs e)
{
form2 = new form2();
form2.Show();
form2.FormClosed += new FormClosedEventHandler(form2_FormClosed);
this.Hide(); // Moved
}

ShowDialog() doesn't make the window modal

I have a windows form that pops up a dialog box if certian conditions are met when the form loads. The problem is the window does not stay on top and I can still click thing on the parent. However, there is a button on the form that when pressed opens the same window, when I do this it works as expected (like a dialog window).
Is there an issue with showing a dialog when a form is first loading?
Are you calling ShowDialog from the Form class? Because it will only set the parent window if called from another Form. Alternatively you can use the overload that has the IWin32Window parameter to specifically set the owner.
can you explain the issue further as this is my code which do not show the form it self until the dialog has been closed either you set the parent or not
private void Form1_Load(object sender, EventArgs e)
{
//your functionality goes here
AboutBox1 box = new AboutBox1();
box.ShowDialog();
}
}
on the other side you can also check with TopMost property
The ShowDialog method needs to be called from the form that you want to be it's parent/owner in order for it to be modal to that form. Alternatively I believe you can set the owner of a dialog directly but I have never needed to do that.
DaBomb,
To do what you want, you will have to call your modal dialog from the constructor of your main form, NOT from the Form_Load event.
Something like this:
public Form1()
{
InitializeComponent();
this.Show();
Form2 popupForm = new Form2();
popupForm.ShowDialog();
}

Categories

Resources