I have a project where a setup dialog (Parent) pops. When the user hit continue a main dialog is opened (Child).
From within the main dialog the user can re-edit the setup dialog (Parent). When the user clicks on X to close the setup dialog, the application terminates.
I assume this is because we close the Parent and it disposes all its children
Is it possible to close the Parent (or hide it) without closing the main dialog (child)?
If not would the following fix would work?
Open the Main Dialog as Parent and make it open the setup dialog (Child)
In the Program.cs file, you probably have a function like this:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
This function is the entry point for your application. The Application.Run() function runs the main loop of the application. The main loop of a graphical application is the place where the event handler triggers the events, the UI gets updated and so on. If an event (for example pressing a button) takes too long to process, the UI hangs. To prevent this from happening, one can use threading.
The Application.Run() function is overloaded, so if the function has a parameter (new Form1() in this case), the form becomes the 'main' form, so the main loop will exit when the form is closed.
To fix this issue, you need to remove the parameter, which will make the main loop run without closing when the form closes:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run();
}
However, this creates 2 problems:
No form is displayed at start-up, because we removed that from the Main function. To fix this, you need to create a new form in the main function, and show it:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 form = new Form1();
form.Show();
Application.Run();
}
The application will not exit when you close the form. If you close all forms, the process will be still running, so you need to call Application.Exit(); when you want the application to exit (e.g. form closing event).
Or, you just cannot understand that a modal window cannot live without a parent. When the parent is minimized, all the modal forms became hidden. When the parent is closed, the same is happening to the modal forms.
So it is a bad practice to trick the model form to stay alive after the parent dies. Just try to stay the pattern in which your second form is just another same equal form as the first one.
Related
Why is the messagebox shown before the form closes?
SomeForm myForm = new SomeForm();
myForm.Show();
MessageBox.Show("Some text");
Do I need to start a new thread, and wait for it to finish? I've never come across this problem before.
You need to use Form.ShowDialog() instead. Form.Show shows a modeless window, whereas Form.ShowDialog shows a modal form, i.e., that the user has to close before continuing.
Your example never actually closes myForm...only shows it. I would expect the code above to show myForm and then immediately show the MessageBox.
If you want myForm to close before showing the MessageBox, you'll need to call myForm.Close() at some point.
The reason for this is that myForm.Show(); starts the opening of a new window, however it is not a blocking call. It's not a dialog, it's a separate window, which runs on it's own.
If you want SomeForm to show as a Dialog (blocking window, waits for close to continue execution), then use ShowDialog. If you want to wait till the window is opened before you show the MessageBox, then add the MessageBox to the OnLoaded on the SomeForm claa.
If it's important that the user not be able to interact with the main form while this other form is being shown then you can use myForm.ShowDialog instead of Show. ShowDialog is a blocking function, so it won't return until the other form is closed. Show, on the other hand, just shows the other form and then immediately returns without waiting for the form to be closed.
If it's intentional that the other form is not being shown modally, and you don't (or can't) make that change, then you can use events to show a message box when the other form is closed.
SomeForm myForm = new SomeForm();
myForm.FormClosed += (form, args) =>
{
MessageBox.Show("Some text");
};
myForm.Show();
This will add an event handler, which fires when the other form is closed, and executes the desired code at the appropriate time.
I am new to win forms (C#). The current form that I'm making has the option to create a new (blank) instance of itself, but if I ever close that first instance, all the others close as well. This is not what I want to happen. (Closing any form opened up from the first doesn't close any others, though)
I was thinking it may be because I am creating a new copy from within one of the copies/objects, so it is tied to that first object so it closes when it does; however, if I open up another form from the one opened from the first one and then close that one that was opened from the first one, the one that I opened up from it doesn't close.
I want it so that I can still close that first form without the others closing, and that when the last one closes, the program stops running.
Is there any way to do this?
You can run as many forms as you need but each in the separate thread
using System;
using System.Threading;
using System.Windows.Forms;
public partial class MyForm: Form
{
public MyForm()
{
InitializeComponent();
}
private void Button1Click(object sender, EventArgs e)
{
var t = new Thread(() => Application.Run(new MyForm()));
t.Start();
}
}
You should not have to close the Entry Point (MainForm) Form. Check the Main() method code in Program.cs code file.
public static void Main(string[] args)
{
// Starts the application.
Application.Run(new Form1());
}
Read this page.
To prevent a form from closing, handle the Closing event and set the
Cancel property of the CancelEventArgs passed to your event handler to
true.
You dont need to create new thread for every form. Just use this:
Form newForm1 = new Form();
this.Hide();
newForm1.ShowDialog();
this.Close();
Shortly:
The first form of every windows application is the main form.
If it closes, so does the application.
(See Program.cs for more details)
To solve this you can call Application.Run (While I don't know if it's smart or not)
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
new Form1().Show(); // any entry point with form
Application.Run(); // without main form
}
}
Program.cs
You can use like this code block.
But when any form closed, application not finished.
(Even if the last a form in application.)
Because application not included mainform.
If application has not any a opened form.
Application will suspend in process. You can see then the task manager.
As a result you will call manually Application.Exit() method in each form close events.
I have two windows forms.Now I have to close first one and show the second form and vice-versa.How can i do it.I was passing this pointer to the constructor of second form and then trying to
close it,but this did not work.I can not use showdialog here.
Add static variables to each form in the Program class:
static class Program
{
public static Form1 f1=null;
public static Form2 f2 = null;
public static FullClose=false;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
f1=new Form1();
f2 = new Form2();
Application.Run(f1);
}
}
Then in the Form_Closing event of each form:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (Program.FullClose==false)
{
e.Cancel = true;
this.Visible = false;
Program.f2.Show();
}
}
(Change Program.f2.Show() to Program.f1.Show() in Form2).
Of course this will stop the application from ever closing, so you should provide an extra button (or similar) that sets a boolean static variable (FullClose) that the Form_Closing events can check to see if they should properly close or not.
You must set in your application, the close is not then main form was closed, then if all forms all closed.
You must pass the pointer of the main form to second form and main form must have second form pointer.
Then implement in your forms OnClosing event, then in her implementation open other form if this success return, else set Cancel to true and return.
In every case there is one form, which represents the live of your application. This form will be started within your Program.cs file by calling
Application.Run(new MyForm());
If you try to start within this form another one and this will afterwards kill his creator, this will always lead to some bad designs.
Instead you should create some super-form. It is invisible and contains the glue code between those two forms. Right after startup it creates both forms and shows the first one. Also it registers to an (self-written) event in both forms which claims to show the other one. If your invisible form gets the event from one form it just makes the sender invisible and shows up the other one.
Last but not least you need in both (or at least in one) forms a second event, which will close the super form thous closing the application.
In C#,
Suppose I am in a form, and I pressed a button I made to close it.
this.Close();
some_action(); //can I do this??
can I perform another action after I closed the form or does the thread die and everything after that is lost?
Depends on what you are trying to do and the context of the statement. If the form being closed is the main form which owns the message loop, you can't do any UI related stuff (e.g. you can't display another MessageBox). If you are not doing it from another window (which doesn't own the message loop), you could do anything (even UI related) as long as you aren't manipulating the closed form object (you'll get ObjectDisposedException just like any disposed object).
By the way, the thread doesn't die as a result of Close. Closing the main window causes the message loop to terminate and not the thread itself. For example, the following program
static void Main() {
Application.Run(new Form1());
Application.Run(new Form2());
}
will display Form2 after Form1 is closed (using a newly created message loop). This proves that the thread is not dead.
If you try to manipulate the form or any of it's controls after calling Close you're going to run into trouble. However there's nothing preventing you from calling some other method - for instance a logging method - after calling Close.
Handle FormClosing Event and do additional action in event handler.
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?