I have a problem with my program.
I have 3 Forms: First one opens a second form. Second one opens a third form or returns to the first form. The third form can open the first or second forms.
This is how I open a second Form:
private void Open_second_form()
{
Form2 myForm = new Form2(Type_person);
this.Hide();
myForm.ShowDialog();
this.Close();
}
The rest of the forms I open exactly the same.
Here is a code for how I close forms. Every Form has this method:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Exit or no?",
"My First Application",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information) == DialogResult.No)
{
this.Close();
Environment.Exit(1);
}
}
When I open the third form I get 3 MessagesBoxes. If I open first form I got only 1 MessageBox.
I want to close all forms while getting only one MessageBox.
I tried a lot of solutions but none worked.
I tried Application.exit();
Please help me :)
Your confirmation message is funny and result is unobvious =D
There are 2 solutions possible to your issue.
1) If user chooses to close application - don't display confirmation anymore
private static bool _exiting;
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!_exiting && MessageBox.Show("Are you sure want to exit?",
"My First Application",
MessageBoxButtons.OkCancel,
MessageBoxIcon.Information) == DialogResult.Ok)
{
_exiting = true;
// this.Close(); // you don't need that, it's already closing
Environment.Exit(1);
}
}
2) use CloseReason to confirm only user actions
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
if(MessageBox.Show("Are you sure want to exit?",
"My First Application",
MessageBoxButtons.OkCancel,
MessageBoxIcon.Information) == DialogResult.Ok)
Environment.Exit(1);
else
e.Cancel = true; // to don't close form is user change his mind
}
}
I'm using this snippet always on my menu form. I hope this helps.
for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
if (Application.OpenForms[i].Name != "Menu")
Application.OpenForms[i].Close();
}
Call the Environment.Exit(0); method
private void btnExit_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
For the form 1, considering the button is called btnForm1To2
private void btnForm1To2_Click(object sender, EventArgs e)
{
using (Form2 myForm = new Form2(Type_person))
{
this.Hide();
myForm.ShowDialog();
this.Show();
}
}
Inside FORM 2, considering the button to page 1 is btnForm2To1, and the button to page 3 is btnForm2To3
private void btnForm2To1_Click(object sender, EventArgs e)
{
// Just close the form 2, as it was called from form 1, this form will be displayed
this.DialogResult = DialogResult.OK;
}
private void btnForm2To3_Click(object sender, EventArgs e)
{
using (Form3 myForm = new Form3(...))
{
this.Hide();
DialogResult form3result = myForm.ShowDialog();
// Now handle the results from form 3 to navigate to form 2 or 1
// In my example, form 3 replies Abort to go back to 1. On cancel (or other dialog results) we will stay on form 2
if (DialogResult.Abort.Equals(form3result))
{
this.DialogResult = DialogResult.OK;
}
else
{
this.Show();
}
}
}
Inside FORM 3, considering the button to page 1 is btnForm3To1, and the button to page 2 is btnForm3To2
private void btnForm3To1_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Abort;
}
private void btnForm3To2_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
}
And if you want that the user confirms his click with a MessageBox, just place them before the this.DialogResult in each button click method
Note that this way is faster than Environment.Exit(0);.
WPF
Set your Window Closing Event in (###Window.xaml)
Closing="Window_Closing"
and then in (###WWindow.xaml.cs)
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach(Window w in Application.Current.Windows)
if(w != this)
w.Close();
}
Windows Form
Go to Form#.cs [Design] >> Form# Properties
Then click on Events
And double-click on FormClosing
In (Form#.cs)
If you're closing from your Startup form, it's better to use this code.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
for(int i = 1; i < Application.OpenForms.Count; ++i)
Application.OpenForms[i].Close();
}
else (Works for any form)
private void Form7_FormClosing(object sender, FormClosingEventArgs e)
{
for(int i = 0; i < Application.OpenForms.Count; ++i)
if(Application.OpenForms[i] != this)
Application.OpenForms[i].Close();
}
If you'd like to close all forms (particularly dialog windows) except for the main form, I've found this function to be useful.
public static void closeAll()
{
FormCollection fc = Application.OpenForms;
if (fc.Count > 1)
{
for (int i = (fc.Count); i > 1; i--)
{
Form selectedForm = Application.OpenForms[i - 1];
selectedForm.Close();
}
}
}
Application.Current.Shutdown();
That's what I use whenever I need to close an entire application. It closes all forms, so great for closing everything. I don't know if this is exactly what you want.
I used this and it worked for me:
for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
if (Application.OpenForms[i].Name != "FRM01"&&Application.OpenForms[i].Name!= "FRM02")
Application.OpenForms[i].Close();
}
Those "FRM" things are the names of my forms, what you can do there is to add as many forms as you like to have as "parents". So each time it iterates it will check if the names of those forms are the ones you wish to keep.
I recommend you add that 'for' into your form closing handler if you wish to control an user from closing parent forms and child forms to still be there.
It is always better to use MDI forms (MDI link here)
Related
I need your help please
I have created a form and insert a timer & progress bar into it
when the value of progress bar reach to 100% I want to close this form and open the main form of my program
I write this code but when I Run the program it show this error :
( Form that is already displayed modally cannot be displayed as a modal dialog box. Close the form before calling showDialog.)
How I can resolve this problem
Form1 MainForm = new Form1();
public Welcome_window()
{
InitializeComponent();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(10);
if (progressBar1.Value == 100)
{
this.Visible = false;
MainForm.Visible = false;
MainForm.ShowDialog();
this.Close();
}
}
}
I think the problem is that you don't stop the timer, so the tick event will be fired even if the progress already reached 100%.
Form1 MainForm = new Form1();
public Welcome_window()
{
InitializeComponent();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(10);
if (progressBar1.Value == 100)
{
timer1.Stop();
this.Visible = false;
MainForm.ShowDialog();
this.Close();
}
}
I want to show another form(Form2) with button click. Basically When the button is clicked in Form1, another form(Form2) should show, this should not hide the Form1 though and should change the button text to "Hide Progress" in Form1. And when this button is clicked again the Form2 should hide and the text in button should change to "Show Progress".
Below is my effort to make this work. When I clicked the Show Progress Button, it brings the Form2 and changes the text in button as well. But when I clicked the button again instead of hiding the Form2, it opens another instance of Form2.
Probably reason behind is that, the bool value is not saved.
Here is my code for button event handler.
public partial class Main : Form
{
public string output_green, output_grey, output_blue, output_black;
public bool visible;
private void button1_Click(object sender, EventArgs e)
{
output progressWindow = new output();
if (visible == false)
{
progressWindow.Show();
button1.Text = "Hide Progress";
visible = true;
}
else
{
progressWindow.Show();
button1.Text = "Show Progress";
visible = false;
}
}
}
How can I achieve that I need to.
Problem:
Each time you click button1 a new progressWindow has been initialized.
Also you are using progressWindow.Show() instead of Hide() in else part.
Solution:
Declare progressWindow out of button1_Click. And then initialize it from button1_Click. Now it will be initialized only once (using if).
output progressWindow = null;
private void button1_Click(object sender, EventArgs e)
{
if(progressWindow == null)
progressWindow = new output();
if (button1.Text == "Show Progress")
{
progressWindow.Show();
button1.Text = "Hide Progress";
}
else
{
progressWindow.Hide();
button1.Text = "Show Progress";
}
}
}
For a shorter solution where the progress window's lifetime persists with the main form :
output progressWindow = new output();
private void button1_Click(object sender, EventArgs e)
{
progressWindow.Visible = !progressWindow.Visible;
button1.Text = (progressWindow.Visible) ? "Hide Progress" : "Show Progress";
}
Here you get rid of the need for the extra boolean since the progress form itself is fully capable of telling you whether it is visible or not.
// Creates a single instance only it it is request.
private Output ProgressWindow
{
get
{
return progressWindow?? (progressWindow= new Output(){Visible = false};
}
}
private Output progressWindow;
private void button1_Click(object sender, EventArgs e)
{
ProgressWindow.Visible = !ProgressWindow.Visible;
button1.Text = (ProgressWindow.Visible) ? "Hide Progress" : "Show Progress";
}
}
I have a login screen and I want to activate it when I press enter in the password textbox.
the problem is that even though it works, when I close the form the app acts like enter is still pressed and the form opens in an endless loop.
here is my code:
private void textBox2_TextChanged(object sender, EventArgs e)
{
textBox2.KeyDown += new KeyEventHandler(textBox2_KeyDown);
}
public void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (user == Username[1] && pass == passwords[1])
{
MessageBox.Show("Login successfull", "Welcome, HR");
UpdateDBForm newEmployee = new UpdateDBForm();
this.Hide();
newEmployee.ShowDialog();
return;
}
}
How tdo I solve this problem?
Thanks.
You are assigning the KeyDown-EventHandler everytime your text changes:
private void textBox2_TextChanged(object sender, EventArgs e)
{
textBox2.KeyDown += new KeyEventHandler(textBox2_KeyDown); // EVIL!
}
This means, that the more often you input data into your textbox, the more the eventhandler will be assigned and when you eventually hit enter it will be called as many times.
Assign the eventhandler once, i.e. in your constructor and this should work.
As #bash.d written you are assigning event multiple times, do it once (either by designer or in constructor (after InitializeComponent call) or in Form_Load event)
private void Form_Load(object sender, EventArgs e)
{
textBox2.KeyDown += new KeyEventHandler(textBox2_KeyDown);
}
also you've written that you want login after user click enter, so you have to add this if:
public void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (user == Username[1] && pass == passwords[1])
{
MessageBox.Show("Login successfull", "Welcome, HR");
UpdateDBForm newEmployee = new UpdateDBForm();
this.Hide();
newEmployee.ShowDialog();
return;
}
}
}
i have created an application in which a menustrip is present in which 2 buttons are there, one for ADD, and another for UPDATE & both controls are in a single form, means a button of add & update is there in a single form, whenever i press add button in menustrip update button will be disabled, and when i press update on menustrip the add button will disable. how to do this? i m doing this by show method but that form is opening multiple times using show().
private void addRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 f2 = new Form1();
f2.MdiParent = this;
f2.Show();
f2.button1.Enabled = true;
}
private void updateRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 f2 = new Form1();
f2.MdiParent = this;
f2.Show();
f2.button2.Enabled = true;
f2.button1.Enabled = false;
}
you simply have to use a single form in this case. try using the singleton approach -
http://hashfactor.wordpress.com/2009/03/31/c-winforms-create-a-single-instance-form/
try using .ShowDialog() instead .Show() and no other form will be able to be clicked on until that one closes.
To do that you'll need to have an instance of that Form outside of those methods that you dismply show if the Form has already been created, or create and show it if it has not (this is the singleton pattern). Here's an example:
Form1 f2 = null;
private void addRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (f2 == null)
{
f2 = new Form1();
f2.MdiParent = this;
f2.button1.Enabled = true;
}
f2.Show();
}
private void updateRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (f2 == null)
{
f2.MdiParent = this;
f2.button2.Enabled = true;
f2.button1.Enabled = false;
}
f2.Show();
}
One question on your disabling of the menu items though, how do you plan on re-enabling them after they have been disabled?
just try to check that form is already opened or not by using its Text Property.. if it is opened just focus on that form other wise show that form as normally
private void button1_Click(object sender, EventArgs e)
{
bool IsOpen = false;
foreach (Form f in Application.OpenForms)
{
if (f.Text == "Form1")
{
IsOpen = true;
f.Focus();
break;
}
}
if (IsOpen == false)
{
Form f1 = new Form1();
f1.Show();
}
}
Try This Guys Its Simple
Actually Its my first project. While I want to convert my VB.Net2008 to C#2010 I have few clarification pls.
In Form2 Properties I set - IsMDIContainer = True. Then the below code to open my MdiChild and now what is my problem when I click the close button, it's also closing the MDIParent. But I need to close only mdichild... for that I tried as like Vb.Net2008 style by the following codes placed in MDIParent Form2, Its not working. Any right directions ...
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3;
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
Form[] MdiChildForms = this.MdiChildren;
int kkk1 = MdiChildForms.Length;
int x = 0;
for (x = 0; x <= MdiChildForms.Length - 1; x += 1)
{
if (MdiChildForms[x].Name == "Form1")
{
kkk1 = kkk1 - 1;
}
MdiChildForms[x].Close();
}
if (kkk1 > 0)
{
// For Not Closing
e.Cancel = true;
}
else
{
// For Closing
e.Cancel = false;
Application.Exit();
}
}
Any Right Directions for Me?
I'm not sure if I understand well what you want to achieve: do you want, when click Parent Form close button, insteed of closing parent form, to close all the child's form? Form2 is your main form (parent MDI container), Form3 is the MDI children, isn't it?
Please try following code and tell if it's what you are asking for:
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3(); //don't forget ()
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//if no MDI child - this is going to be skipped and norlmal Form2 close takes place
if (this.MdiChildren.Length > 0) //close childrens only when there are some
{
foreach (Form childForm in this.MdiChildren)
childForm.Close();
e.Cancel = true; //cancel Form2 closing
}
}