C# form closing at program end - c#

I have a windows forms question:
Program.cs:
Application.Run(new frmStart());
frmStart: on btnLoad_Click,
frmLoad formLoad = new frmLoad();
formLoad.Show();
this.Hide(); // if I do a this.Close(); after it shuts down and doesn't get to show the form
frmLoad: on btnCancel_Click:
Application.Exit();
// or this.Close();
// or even: base.Close();
The form disappears but the program doesn't end, I still have to press the blue "Stop Debugging" to make it stop.
I have been looking... I know it is possible to make the program really stop, and not just freeze when you close the second form, even if you don't keep the first form on the screen, but can't remember and can't figure out how.

Ack, -1 on Application.ExitThread!
The issue is that you haven't closed the main form. The simplest way is to hook onto the 2nd form's Closed event and have it close the main form. For example the code to open the 2nd form changes to:
var newForm = new frmLoad();
newForm.FormClosed += (closedSender, closedE) => Close();
newForm.Show();
Hide();
This essentially sets up so that when the frmLoad form closes, the main form calls it's Close() method. I used a Lambda expression for the event handler, but you can just as easily create a private method accepting an (object sender, EventArgs e) and point .FormClosed at it.
*Edit: Sorry, missed that you only want to close on certain state. In which case on your frmLoad, create a public property such as:
public bool UserCancelled
{
get;
private set;
}
where the Cancel button sets this to True before closing the form. Your event handler in the main form changes to:
var newForm = new frmLoad();
newForm.FormClosed += (closedSender, closedE) =>
{
if (newForm.UserCancelled)
Close();
};
newForm.Show();
Hide();

In frmStart add:
public static frmStart Current;
Then in the constructor add:
Current = this;
Then in frmLoad: on btnCancel_Click:
frmStart.Current.Close();

You really should call Close() on both. That's the only clean way as otherwise the first form never is told to close down and doesn't clean up.
You may know that it's safe to do this, but someone else working on the code later may add code in the OnClose in the first form that they need called. They will say not nice things about you when they finally figure out why their code is not called.
If you close both, then your app will exit.

Please use the Application.ExitThread() method, the method exits the message loop on the current thread and closes all windows on the thread.
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.exitthread

I vote yuck on all the answers. Override Form Closing in your primary form and close the secondary form first.

Related

First form not closing, second not opening

I'd like to have a welcoming form, named the StartForm. This closes, then opens my MenuForm.
Current problem is: First one stays open, doesn't close to show the second one.
I tried several things, like simply showing and hiding them. I now try Application.run and then hide it. Unfortunately it stays open. And doesnt Application.run the second form.
static void Main()
{
Form StartForm = new Main();
MForm MenuForm = new MForm();
Application.Run(StartForm);
//
Task.Delay(500).ContinueWith((t) =>
{
StartForm.Hide();
Application.Run(MenuForm);
});
}
I expected this to Close the first form after waiting the delay, but it stays open.
Calling Application.Run() causes a new application message loop to begin running on the current thread. If a subsequent call to Application.Run() is made while the first application is running an InvalidOperationException is thrown according to the docs. However, this is not actually possible in your case as your call to Application.Run() is being invoked on the UI thread, which blocks the execution of any following code until it exits.
Instead, what we need is to bootstrap the application by using Application.Run(new Main()) and then inside of the Main form we will handle the displaying and hiding behaviour.
Here is how I would suggest achieving this:
Firstly, in your Main method, replace everything with Application.Run(new Main());.
Then inside of your Main form create a method like the following:
private void Main_Shown(Object sender, EventArgs e)
{
Task.WaitAll(Task.Delay(500));
this.Hide();
var menuForm = new MForm();
menuForm.Closed += (obj, args) => { this.Show(); };
menuForm.Show();
}
And lastly, go into your Main.Designer.cs file and make sure you subscribe the Shown event to Main_Shown method you just created in the InitializeComponent method like so:
this.Shown += new System.EventHandler(this.Main_Shown);
Explanation of what is going on here:
According to the docs the Form.Shown Event gets fired the first time a form is shown to the user. This is perfect for this use case, so we 'hook' into it and respond to it by awaiting a delay of 500 milliseconds.
Afterwards we hide the current (Main) form, create the new (MForm) form and show it. But the more important detail is that we subscribe to that form's Closed event so that when it is closed by the user, the Main form shows itself again.
use timer to Open Second form in Firstform
and Hide Firstform after show Secondform.
like this.
Main
static void Main()
{
Form StartForm = new Main();
Application.Run(StartForm);
}
FirstForm
set timer with interval 5000 and Enable it.
private void timer1_Tick(object sender, EventArgs e)
{
MForm MenuForm = new MForm();
this.Hide();
MenuForm.Show();
timer1.Stop();
}

WinForm closes even after removing Close()

I'm encountering strange behaviour from my WinForms app in VS 2010. I launch a new form using straight-forward code:
MainDisplayForm.cs:
using (MyForm myForm = new MyForm())
{
var result = myForm.ShowDialog();
if (result == DialogResult.OK)
{
// do stuff
}
}
I added a Cancel button to MyForm that displayed a confirmation MessageBox to the user and then called this.Close(). I later removed the this.Close() line because I added a dedicated Close button. However, whenever I press Cancel the instance of MyForm still closes!
MyForm.cs:
private void cmdCancel_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show( ... )
// clear the form if user really wants to quit
// this.Close()
// even after removing the above line, program still jumps to FormClosing
}
When I debug line-by-line after clicking on the Cancel button, the program flow just jumps to MyForm_FormClosing after it hits the end of cmdCancel_Click. I created a new button and set its click event to cmdCancel_Click and it did not close the form - so the problem is solved, but I am still wondering if this is just a bug, or something else? I also made sure to reset the DialogResult property of my Cancel button back to None (after changing it to Cancel before I introduced the dedicated Close button).
When exiting the scope of 'using' statement, it calls 'myForm.Dispose()' (that's the whole point of 'using' - to make sure Dispose()is called). This in turn destroys 'myForm' instance, including closing the window.

Owned form and mdi parent

this is my scenario and hope you can solve it for me
I have a MDI container form called "MainForm". In MainForm there is a simple form call "Form1". In Form1 there is a button. every time you pushed it, It open a new form which instance of "Form2". The followng code is click button event.
Button_Click()
{
Form2 frm=new Form2();
frm.mdiparnt=this.MdiParent;
this.addOwnedForm(frm);
frm.Visible=true;
}
and the following code tries to close owned forms when the user close Form1
Form1_CloseEvent()
{
foreach(var item in this.ownedForm)
{
item.close();
}
}
But when the debugger steps into close event, just close Form1, and the form2 instances remain open. what should I do to solve it
I think you are not setting up the event. Do it like this.
Add it to your Button_Click() method:
this.FormClosed += Form1_FormClosed;
Here is the method:
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
foreach(var item in this.ownedForm)
{
item.close();
}
}
first of all this code does not compile!
you have several syntax errors: mdiparnt, addOwnedForm, ownedForm, close
you are probably not sharing your actual code and that's gonna be a problem to help you if it's not your code.
now in Button_Click() event you are doing
frm.mdiparnt=this.MdiParent;
this.AddOwnedForm(frm);
even though you only need
this.AddOwnedForm(frm);
or an exception will be thrown. i've checked this code and it's working just fine

FormClosing with CloseReason = UserClosing doesn't work expectedly?

I have a main form, in the class of this form, I declare another form. This form lives with the main form until the main form is unloaded. There is a button on the main form, clicking this button will show the member form (I mentioned above). I want to prevent the member form from closing when user closes that form and I added the following FormClosing event handler for that form:
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e) {
if(e.CloseReason == CloseReason.UserClosing){
e.Cancel = true;
Hide();
}
}
That works OK for that form. However if user closes the main form, this form is not closed, and it's hidden somewhere making my application seem to run silently. I want this form also to be closed. This is very simple by adding some FormClosed event handler for my main form to close the member form manually. Closing it manually is OK, but why do I have to do that? It seems that when user closes the main form, the FormClosing event of the member form is fired with a parameter FormClosingEventArgs passed in and the CloseReason is the same as the CloseReason of the main form (which is UserClosing). I don't understand this, I thought the CloseReason of the form is UserClosing only when user clicks on the X button, I thought the CloseReason for my member form is something like "MainFormClosing".
Is there some way to close the member form automatically as by default?
UPDATE
Here is the method showing the member form (showing it as a dialog):
private void ShowMemberForm_Click(object sender, EventArgs e){
memberForm.ShowDialog();
}
But I don't think this matters, because when I load my main form, even I don't need to click on the ShowMemberForm button, and try closing my main form first, it doesn't still close the member form.
Thanks!
UPDATE
There is something strange here, I've tried commenting out the line e.Cancel = true, or even all the FormClosing event handler and the problem is still there. This is so strange, it works OK before, I've just added the member form and this form relates to some Thread handling, but the thread starts only when a button on the member form is clicked. I didn't click that button.
What I have done in the past is set a flag when programatically closing
so in the MemberForm
private bool _ForceClose = false;
public void ForceClose()
{
_ForceClose = true;
this.Close();
}
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(!_ForceClose)
{
e.Cancel = true;
Hide();
}
}
Then in your MainForm you can call
memberForm.ForceClose();
From within your MainForms FormClosing method or from your MainForms Dispose() or Deconstructor.
It's low tech, but it works. Im not sure if you should put _ForceClose = true in your MemberForm's Dispose method, i'm fairly certain when it gets there its already been closed BUT it couldn't really hurt.

Very strange bug when using Show Dialog on C# Winform

I have created 2 forms in VS Studio 2008 Express Edition and declare them with public static in main program.cs file
I just want to switch between the two forms with ShowDialog and Close but when trying to close the second form and open the first form again with showdialog it says I cannot use showDialog when the form is already visible, whereas it isn't true since I closed it before to show the second form.
It asked me to set the form visible property to false before using showdialog, so I did it
internal static void CloseSecondForm(FirstForm FirstForm)
{
FirstForm .Close();
SecondForm.Visible = false;
SecondForm.ShowDialog();
}
But then it says I cannot use ShowDialog because the form is already shown in Dialog Mode and that I must close it. So I did what it asked
internal static void CloseSecondForm(FirstForm FirstForm)
{
FirstForm .Close();
SecondForm.Visible = false;
SecondForm.Close();
SecondForm.ShowDialog();
}
But it still pretends that the form is already opened with ShowDialog !
Is this a Bug in my prog or in Winform ?
Update: this is the whole code I posted in 5th answer (I want to use showdialog and not show because I may have a 3rd form in Background that I don't want the user to access):
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 = new Form1();
Form2 = new Form2();
Form1.ShowDialog();
Application.Run();
}
// called from Form1 BUTTON
internal static void ShowForm2(Form1 Form1)
{
Form1.Hide();
Form2.ShowDialog();
}
// called from Form2 BUTTON
internal static void ShowForm1(Form2 Form2)
{
Form2.Hide();
Form1.ShowDialog();
}
I tried with Hide as suggested but it doesn't work either. This is the whole program, what I want to do is very simple: I have two forms initially created in program with one button on each form to close self and open the other. I put all the logic in program.cs below:
using System;
using System.Windows.Forms;
namespace twoforms
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
///
public static Form1 Form1;
public static Form2 Form2;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 = new Form1();
Form2 = new Form2();
Form1.ShowDialog();
Application.Run();
}
// called from Form1 BUTTON
internal static void ShowForm2(Form1 Form1)
{
Form1.Hide();
Form2.ShowDialog();
}
// called from Form2 BUTTON
internal static void ShowForm1(Form2 Form2)
{
Form2.Hide();
Form1.ShowDialog();
}
}
}
This is a bug in your program. When you have two instances of a form (call them A and B), you obviously cannot continually show one from the other using ShowDialog. If you could do this, it would mean that A shows B modally, and B then shows A modally, and A then shows B modally etc. This would be like building a house with two bricks, where you just keep taking the bottom brick and placing it on top of the other.
Your best solution is to not make these forms static, and instead just create new instances of each form as you need them. Your second-best solution is to use Show instead of ShowDialog; if you only have one of these forms showing at a time anyway, ShowDialog has no purpose.
Static forms are almost always a bad idea (and I'm being polite about "almost"). If your forms are taking a long time to create, you should identify what resource is taking so long to load and cache that as a static object, instead of trying to cache the entire form as static.
This is from MSDN:
When a form is displayed as a modal
dialog box, clicking the Close button
(the button with an X at the
upper-right corner of the form) causes
the form to be hidden and the
DialogResult property to be set to
DialogResult.Cancel. Unlike modeless
forms, the Close method is not called
by the .NET Framework when the user
clicks the close form button of a
dialog box or sets the value of the
DialogResult property. Instead the
form is hidden and can be shown again
without creating a new instance of the
dialog box. Because a form displayed
as a dialog box is not closed, you
must call the Dispose method of the
form when the form is no longer needed
by your application.
So once you show a form using ShowDialog and you now want to close it, just let it return DialogResult.Cancel
This will hide (it will still be in memory) your first form. Now you can call ShowDialog on your second form. Again, if you want to switch to first form then let the second form return DialogResult.Cancel and now just call ShowDialog on first form.
Try to use Hide() instead of Close(). I had a similar problem in the past and Hide() worked for me.
I think you should really treat Modal dialogs like method calls, and try to use the result of the Call to ShowDialog to determine what you want to do next? if you have a requirement to switch between dialogs you should use some sort of result (Maybe simply DialogResult see my example) or a public property of the dialog to determine if you need to Show another dialog, If you need to call one modal dialog from another you should think of it like a stack of forms, that effectively (even if you do make one invisible before calling another) place one upon the other. You really want to minimise this stacking of forms.
This is a bit of a contrived example but each form here simply has a single button with DialogResult set to OK.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool exit = false;
while (true)
{
if (exit) break;
using (Form1 frm = new Form1())
{
switch(frm.ShowDialog())
{
case DialogResult.OK:
break;
default:
exit = true;
break;
}
}
if(exit) break;
using (Form2 frm = new Form2())
{
switch(frm.ShowDialog())
{
case DialogResult.OK:
break;
default:
exit = true;
break;
}
}
}
}
to exit simply click the red close (x) button.
Check out the difference between Close and Hide. And the difference between Show and ShowDialog.
It's not really clear to me what you want to achieve; you only (partially) describe what you done in code and the symptom of the problem you are having. Could you please describe what you are trying to do?
If your goal is to have two dialogs showing from your main window where only one of the two can be visible at the same time, then there are perhaps better solutions than using two static (=global) public Form instances that you show using ShowDialog.
Have you thought of using one dialog Form for this that just changes it appearance depending on the situation?

Categories

Resources