To close C# Forms Application - c#

I have 2 forms ...when i start the application..and use the close "X" from the title bar the entire application closes...now when i select an option from the 1st form in my case it is a button "ADD" as its a phonebook application..it goes to the 2nd form as i have used 1stform.hide() and 2ndform.show()...now when i do "X" from the title bar it doesnt shutdown completely as the 1stform is not closed....how to program it in such a way tht any stage the entire application should close

Your first form is set as the startup form. That means whenever it gets closed, your entire application is closed. And conversely, your application does not close until it gets closed. So when you hide the startup form and show the second form, the user closing the second form does not trigger your application closing because they have only closed a secondary, non-modal dialog.
I recommend changing your design so that the startup form is also the main form of your application. No sense trying to work around built-in functionality that can actually be useful. You want the application to quit when the main form is closed, no matter what other child forms are opened.
But the quick-and-dirty solution in your case is to make a call to Application.Exit. That will close all of the currently open forms and quit your application immediately. As I said just above, I don't so much recommend this approach because having to call Application.Exit from every form's FormClosed event handler is a sign that something has gone seriously wrong in your design.
If the single startup form paradigm doesn't work out for you, you should look into taking matters into your own hands and customizing the Main method in your Program.cs source file. See the answers given to this related question for some ideas on how that might work for you.

What you can do is to use the Form's FormClosing event, and add the following code:
Application.Exit();
This will stop the entire application, and close all windows. However, if a background thread is running, the process itself will survive. In this case you can use:
Environment.Exit();

Add a Application.Exit on every forms's Closing event
like this:
Create an closing event handler first
private void Form_ClosingEventhandler()(object sender, CancelEventArgs e)
{
//Perform any processing if required like saving user settings or cleaning resources
Application.Exit();
}
then bind this event to any form you create.
//Where you create new form and show it.
Form1 frm= new Form1();
//set other properties
frm.Closing += new EventHandler(Form_ClosingEventhandler);
Form2 frm2= new Form2();
//set other properties
frm2.Closing += new EventHandler(Form_ClosingEventhandler);

Surely you don't want to shut down the entire application after the user adds a phone number? You just need to make sure that your main window becomes visible again. Write that like this:
private void AddButton_Click(object sender, EventArgs e) {
var frm = new AddPhoneNumber();
frm.StartPosition = FormStartPosition.Manual;
frm.Location = this.Location;
frm.Size = this.Size; // optional
frm.FormClosing += delegate { this.Show(); };
frm.Show();
this.Hide();
}

Related

Windows forms Form closed event not working with opening a new form

I have some code meant to open a new windows form when one is closed, and yet I get nothing, no error.
I've tried a few different methods for opening a new form on a Form.FormClosed event.
This is the code I have right now:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Form1 myForm = new Form1();
myForm.Show();
}
But yet I get no error, nothing.
I'm expecting for a new windows form to be opened when I close another one.
Any help would be appreciated, thanks!
The problem is that as soon as the first Form1 instance closes, your application shuts down and exits because the application message loop is defined with the initial Form instance, and it is just waiting for events on that form until it closes. On closing, the application will exit, opening a new form doesn't stop this process.
You need to adjust the Main() method in Program.cs to look something like this:
[STAThread]
static void Main()
{
// ... Application configuration as required here
new Form1().Show(); // The first form instance is now no longer bound to the Application message loop. Start it before we begin the run loop
Application.Run(); // Don't pass in Form1
}
Your original code should now work. I might add however, this is not a great user experience. Carefully consider what you're trying to achieve, and perhaps consider alternatives - do you just need a "reset form" button? Or is the primary goal to prevent a user from closing the application? If the latter, you can remove the Close icon altogether.
Perhaps something simple to get your going forward.
private Form1 myForm = new Form1(); //Declare the form as a private member variable
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
e.Cancel = true; //Cancel the closing so this object stays alive
this.Visible = false; //Hide this form
myForm.Show(); //Show the next form
}
Please note #pcdevs comment. You'll need a way to indicate the form is being closed/application quiting vs progressing to the next step/form. You might want to look at some CodeProject articles about "C# Winform Wizards", those sequential dialog prompt apps...

Timer that closes modal form in Windows Forms

I have several modeless Forms with grids to show data in a MDI Windows Forms app (Form1 in example code). Each of these Forms has a button that opens another Form as modal using ShowDialog (Form2 in example code), which allows editing the data shown in Form1. These modal forms have a Cancel button that closes the form without saving changes by setting DialogResult to Cancel.
I want to implement a timer that closes all forms after a certain time has elapsed from user login into the app. The problem arises if the timer triggers while a modal Form is open.
public partial class Form1 :
{ //Constructor ommited for brevity
private void btnEditData_Click(object sender, EventArgs e)
{
var form2 = new Form2();
timer1.Tick += (_, __) =>
{
form2.DialogResult = DialogResult.Cancel;
this.Close(); // this executes before form2.ShowDialog returns
};
timer1.Interval = 5_000;
timer1.Enabled = true;
form2.ShowDialog();
reloadData(); // here Form1 is already disposed because Close
// has been called on it. An exception is thrown as a consequence
}
private void reloadData()
{
if (this.IsDisposed)
// simulate using a disposed form
throw new ObjectDisposedException(this.Name);
}
}
My intention would be to somehow schedule the call Form1.Close() after form2.ShowDialog() has returned and the btnEditData_Click method has finished, so that there would be no danger of using a disposed form.
EDIT
After seeing your code, I'd suggest to introduce a third option in your Tick event handler that would be used to decide if you have to close the form. For example, Abort.
timer1.Tick += (_, __) =>
{
form2.DialogResult = DialogResult.Abort;
};
if (form2.ShowDialog() == DialogResult.Abort) Close();
else reloadData();
First thought: keep it simple and keep it clean. You don't have to keep track of your open forms, in an MDI application there is MdiChildren property of the parent form that will give you all the forms.
Then, to handle the closing part, you can use existing functionalities in .Net.
A difficult approach is using P/Invoke. You load Windows DLLs and use their functions to enumerate through all your forms and close which one you want. You can also simulate a click on Cancel button. You have to start with EnumWindows function (to identify the forms) and EnumChildWindows for form's children. I like this option because you have full control of your forms and controls, but can give you headaches if not familiar with the concept.
You can have a look at FormClosing event and subscribe to it. This event fires before the form is closed and you can make the clean up using it.
Using OOP - inheritance and override. Either you create a base form with custom close function that does the cleaning (and then inherit all your forms through it), or override form's close functions to achieve your goal.

How to bring the main form back to the front after the file open dialog is closed

My C# application starts by opening a form. In the constructor for that form I "showDialog" an openfiledialog. After selecting a file to open, the openfile dialog closes, the file is loaded and the contents displayed in the main form but the main form is buried behind every other open window on my desktop.
I have to find it in the task bar and bring it to focus. I just started the application, I want the form to have focus.
I have written other applications that do not use the openfiledialog and when I start them the main form opens with focus as you would expect.
How do I make the main form get focus after the openfiledialog closes?
I have tried
this.focus(),
this.activate(),
this.bringtofront();
and this.TopMost = true;
None of them make any apparent difference at all.
I have research this problem extensively and this are the things everyone suggests and say work, but they don't work for me. Some have insinuated that I am violating all that is holy by trying to make my form topmost. However, I don't think very many people would like to open an application and have the main form for it show up behind everything else.
Any one have any other ideas about how to make sure my form is "in front", topmost, has focus?
When you do it this way, your application will have a brief moment where no window is available to receive the focus after the dialog closes. Windows is forced to find another window to give the focus to, that will be a window of another app. Your main window eventually appears, now behind that other's app window.
Display the dialog in an event handler of the Shown event instead. Or use the boilerplate File + Open command.
SOLUTION: this.Activate(); works but if called from the form Load event.
This will set the window on top:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
private void Form1_Load(object sender, EventArgs e)
{
....
//after your code place the call to the function at the end.
SetForegroundWindow(this.Handle);
}
Althought as Mr. hans said and very well you are better off with another design.
If you can, move the ShowDialog out of the constructor, or try putting this in the constructor:
this.Shown += OnShown;
and move your ShowDialog to here:
private void OnShown(object sender, EventArgs eventArgs)
{
var result = new OpenFileDialog().ShowDialog();
}

MDI application issues

General description of application:
Main form as MDI Container. On application start, if there is no xml file for database configuration (it is checked in Main form) Main form i call another form as showdialog() to fill all database info to build connection string. Then i close form and open another for login, then i get back to Main form, which has Split Container (2 panels: 1-menu on top, 2-content from child forms).
I open forms with:
private void PlanButton_Click(object sender, EventArgs e)
{
plan.TopLevel = false;
KontenerMenu.Panel2.Controls.Add(plan);
plan.Dock = DockStyle.Fill;
plan.Show();
}
and close form with:
private void Plan_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = false;
this.Hide();
}
Problems i have with app:
1. When i hit Cancel button when i open ShowDialog() form for database app crashes. Cancel button is simply:
private void cancelButton_Click(object sender, EventArgs e)
{
Application.Exit();
}
2. I have problem with clicking button to open/close/open again child forms. When i hit 'X' and want o open, app crashes with exception that it cannot refer to non-existing object
3. I have several buttons when i hit one and then another one it is always below the first one and not on the top
4. For example my form is 200x200 and in right down corner i have button (so location let's say 190x190) and i hit maximize button. My button is still on 190x190 and i would like to have it on down right corner. I couldn't find any property for that. Is there any or i have to write some code for that.
I'm not sure I understood your questions. Please make them clear.
But as an answer to question #4, there's an anchor property that does what you want.
Instead of trying to exit the application from within the dialog form itself you should return a DialogResult value and test that in the main form. The cancel button on the dialog doesn't need any code, just set its DialogResult property to 'Cancel' and if you have an Ok button set its DialogResult to 'OK'.
DialogForm f = new DialogForm();
DialogResult r = f.ShowDialog();
if (r == DialogResult.Cancel)
{
Close();
}
I can immediately see a number of problems with you code, including:
If you're going to add controls dynamically using Controls.Add, you should make sure the controls you're adding are dynamically created using new(). I get a sense that you don't have a clear understanding of object lifetimes and the WindowForms control life cycle.
The Application.Exit method should be used only in unusual cases. It's purpose is to achieve exactly the result you're observing - to immediately "crash" the application. The easiest way to have a button close a modal dialog is the set the DialogResult property of the button.
Winforms has a very elegant system for placement of control on a variable sized window. In order to use this system, you should familiarize yourself with the Anchor and Dock properties that are available on all controls.
It looks like what you're doing is attempting to learn WinForms by trial and error. You can do this, but it will take much longer and be much more painful that getting a hold of a good tutorial, book, or perhaps even attending a class if you can manage it. That will allow you to take these issues one at a time and have a much more enjoyable learning experience.

How can I have multiple forms start at once in C# .NET?

In C#, I'm trying to get two forms (but probably three eventually) to start at the same time... I've tried adding a new "Application.Run" to my Program.cs file, but it only starts the second form after the first one closes.
So how could I create something like that? Similar to a program like Lazarus.
You simply have to show your form before invoking Application.Run().
var form1 = new Form1();
var form2 = new Form2();
form1.Show();
form2.Show();
Application.Run();
Word of warning here, since no form is tied to the Application.Run call, you will need a way to tell the application to exit when all your forms are closed.
To display a Form you have 2 methods:
Show() - display a non modal dialog (is what you want); also you need to add Application.Run for to work.
ShowDialog() - display a modal(some blocking) dialog; a modal dialog capture all the input for the current thread.
If you want a interface like Lazarus, google by the "MDI application".
I think you probably should decide on one form to be your "primary" form, and then have the other form(s) be member variables of your main form. Then just have the Load event of your primary form also show the secondary form(s).
so,
class MainForm : Form {
readonly Form _otherForm = new OtherForm();
override OnLoad(EventArgs args) {
_otherForm.Closed += // add a handler for what happens when otherForm is closed.
_otherForm.Show();
base.OnLoad(args);
}
}
There may be a better way of doing this but that's what I would do as a first shot.

Categories