I would like to make X control closing window to hide current display previous form.
In form1 I got:
private void button1_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Tag = this;
form2.Show(this);
Hide();
}
and then when I click X I would like to show previous and hide the current.
You should not override Form.OnFormClosing() for just this. The Form.FormClosing event provides this functionality for you:
void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// Prevent the user from closing this window, minimize instead.
if (e.CloseReason == CloseReason.UserClosing)
{
this.WindowState = FormWindowState.Minimized;
e.Cancel = true;
}
}
You can override OnFormClosing to do this.
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.WindowsShutDown) return;
// DO WHATEVER HERE
}
You have to keep track of your instanced forms.
// Program.cs
public static FormA Instance;
public static void Main()
{
Instance = new FormA();
Instance.Show();
}
Then:
// FormB.cs
private void button1_Click(object sender, EventArgs e)
{
Hide(); // Hide current...
Program.Instance.Show(); // Show previous...
}
Related
I have a dialog window with a listbox containing >3000 items that takes a long time to initially load. To load this dialog, I created an instance var dlg = new frmDlg(); and then when I need this dialog, I open it with dlg.ShowDialog(this); Although this reduced the number of time the listbox needs to be initialized, it still takes a long time to show the form as the dialog is unloaded from memory after the dialog closes, requiring the visual elements to be reloaded. Is there any way to keep this from happening? With a normal form, I would just hide the window instead of closing it, but this does not seem to work for dialog windows.
Add the following members to the frmDlg:
private bool keepHandle;
protected override void OnFormClosing(FormClosingEventArgs e)
{
keepHandle = e.CloseReason == CloseReason.UserClosing;
base.OnFormClosing(e);
}
protected override void DestroyHandle()
{
if (!keepHandle)
base.DestroyHandle();
}
This should prevent the dialog's handle from being destroyed when the dialog closed by the user.
Form1:
public partial class Form1 : Form
{
private Form2 reusable = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (reusable == null) reusable = new Form2();
reusable.ShowDialog(this);
switch (reusable.DialogResult)
{
case DialogResult.OK: MessageBox.Show("Ok clicked."); break;
case DialogResult.Cancel: MessageBox.Show("Cancel clicked."); break;
case DialogResult.None: MessageBox.Show("Form Closed."); break;
}
}
}
Form2:
public partial class Form2 : Form
{
private DialogResult dialogResult = DialogResult.None;
public new DialogResult DialogResult
{
get => this.dialogResult;
set => this.dialogResult = value;
}
public Form2()
{
InitializeComponent();
}
private void Form2_Shown(object sender, EventArgs e)
{
this.dialogResult = DialogResult.None;
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
this.dialogResult = DialogResult.OK;
this.Close();
}
private void button2_Click(object sender, EventArgs e)
{
this.dialogResult = DialogResult.Cancel;
this.Close();
}
}
^ Several caveats: you can no longer use the result from ShowDialog result, and you need to create your own DialogResult property, or just use a completely different / new property to represent how your dialog was hidden.
You also can't use the Button.DialogResult property anymore on any buttons, and you need to implement your own button click events to handle setting the dialog result.
This is all because of stuff that happens under the hood in the .net framework when you call ShowDialog result.
Also, Dmitry's example on using the e.CloseReason is valid too - you might want to allow closing for stuff like the application closing. That way you can also handle the FormClosed event and do any rapid cleanup you need to do before the application closes.
My main form opens child form. When the child form closes the parent form needs to perform some tasks. How the parent can know that the child form was closed.
I have a workaround - the hidden button and I invoke PerformeClick method when the child raises the closing event.
Is there any better (more correct) way of doing it?
Add a listener event for your main/parent form when you instantiate child form. Example below:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.CustomFormClosed += CloseListener;
f2.Show();
}
private void CloseListener(object sender, EventArgs e, string test)
{
Console.WriteLine(test);
}
Edited for Custom Delegates & Events
Form2 code:
public delegate void CustomFormClosedHandler(object semder, FormClosedEventArgs e, string text);
public event CustomFormClosedHandler CustomFormClosed;
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
CustomFormClosed(sender, e, "Hello World!");
}
One way to do this is:
return DialogResult from FormClosing event handler of Form2
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
this.DialogResult = DialogResult.OK;
}
Run modal ShowDialog() on a new thread from Form1 and wait for the DialogResult
private void button2_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
System.Threading.Tasks.Task.Run(() =>
{
if (f2.ShowDialog() == DialogResult.OK)
{
// do here whatever you want to do
MessageBox.Show("Form2 closed");
}
});
}
All you have to do:
1: Add public static method in the parent form:
public static void ChildFromClosed()
{
//Inform here
MessageBox.Show("Child form is closed!");
}
2: Add a (FormClosed) event in the child form that calls that method from the parent form:
private void frmChild_FormClosed(object sender, FormClosedEventArgs e)
{
//calling the static method in Parents form
frmParent.ChildFromClosed();
}
I have multiple form with the same design like:
In Form1{
Form2 = new Formtoopen();
Form2.Resize += new EventHandler(Form2_Resize);
Form2.FormClosing +=new FormClosingEventHandler(Form2_FormClosing);
}
and then the events:
In Form1{
protected virtual void Fly_Form2_Closing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Fly_Form2.Hide();
}
}
protected virtual void Fly_Form2_Visiblechanged(object sender, EventArgs e)
{
//some code
}
}
I would like to add the Form2 Type in the EventArgs that is empty from now.
I think it would make my code simpler as I have multiple Form sharing the same code.
How could I do that? I thought about the event custom arguments way but i'm not sure with Type...
Could you help me?
Thanks
Here is something that works:
In Form1{
Form2 = new Formtoopen();
Form3 = new Formdata();
Form2.FormClosing +=new FormClosingEventHandler(Form_FormClosing);
Form3.FormClosing += new FormClosingEventHandler(Form_FormClosing);
}
In Form1{
protected virtual void Form_Closing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
((Form)sender).Hide();
}
}
Retrieving the sender with cast Form from the object sender.
Thanks a lot M.Passant!
When I click a button a form is opened, but if the form is already open, then the app should display the message "Form already open!" and do nothing else.
My problem is, once I close the window [x] I can't open the form again.
Here's the code:
Form2 decript_form = new Form2();
private void button2_Click(object sender, EventArgs e)
{
if (!decript_form.Visible)
decript_form.Show();
else
MessageBox.Show("Form already open!");
}
When the "Close" button is pressed, you want it to just "hide" the form...you need to use e.Cancel to stop it going on and closing.
If you really really want to close the Form2 window instead of hiding it while your application is running....then call ReallyClose....so that the close isn't prevent (then create a new decript_form or null it out).
(Alternatively decript_form.Dispose() would force real closure too)
public partial class Form2 : Form
{
private bool m_bReallyClose = false;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (!m_bReallyClose)
{
this.Visible = false;
e.Cancel = true;
}
}
public void ReallyClose()
{
m_bReallyClose = true;
this.Close();
}
}
public partial class Form1 : Form
{
Form2 decript_form = new Form2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (!decript_form.Visible)
decript_form.Show();
else
MessageBox.Show("Form already open!");
}
private void button2_Click(object sender, EventArgs e)
{
decript_form.Dispose(); // or .ReallyClose();
decript_form = new Form2();
}
}
I assume that you talk about the [x] on Form2 being pressed. It that's the case you should handle the Closing event in Form2() and add
this.Hide();
to the handler. Even a closed window is still 'shown' until it is hidden.
class Form2
{
override protected void OnClosing(CancelEventArgs e)
{
Hide();
}
}
I have a button called btnChallenge. The desired action is when it is clicked, the form cannot be closed.
Here is what I have so far:
public void btnChallenge_Click(object sender, EventArgs e) { }
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// not sure on this if statement
if (btnChallenge.Click)
{
e.Cancel = true;
}
}
You could try it this way:
Declare a private variable inside a form:
private bool _closedFromMyButton;
Then on FormClosing event check that property:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_closedFromMyButton) // If closed from MyButton, don't do anything. let the form close.
return;
Hide(); // Hide the form (or not, it's up to you; this is useful if application has an icon in the tray)
e.Cancel = true; // Cancel form closing
}
Then on some button click (if desired), put this code to close the form only from that button (or menuitem or toolbar button, etc.):
private void MyButtonClick(object sender, EventArgs e)
{
_closedFromMyButton = true;
Application.Exit(); // Or this.Close() if you just want to close the form.
}
You could define a variable which goes to true when you press the button and check on close if the variable is true
e.g.
private bool btnClicked = false;
public void btnChallenge_Click(object sender, EventArgs e)
{
btnClicked = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if(btnClicked)
{
e.Cancel=true;
}
}
You can just call the this.Close() method, this will call the Form1_FormClosing event:
public void btnChallenge_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//code here...
}
If you want to prevent the users by closing your form just after they have pressed some other button, then this code will help you.
private bool close_state=false; // hold the button state
// method to change the close_state by button click
private void Button1(object sender, EventArgs e)
{
close_state = true;
// if required you can toggle the close_state using an if statement
}
// Then on FormClosing event check that property:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (close_state) {// If the button is pressed
e.Cancel = true; // Cancel form closing
}
}
You may implement some other way to close the form....