i have 3 forms.
main_frm is MDI
app_frm is child MDI
progress_frm just a form that shows progress of app_frm
in the progress_frm form i have a button named "cancel" that closes the progress_frm form. Then have the following event on closing the progress_frm.
private void frm_progress_Closing(object sender, FormClosingEventHandler e)
{
Form currentForm = Form.ActiveForm;
Form app_frm_temp = currentForm.ActiveMdiChild;
app_frm_temp.Dispose();
}
I am expecting that the form app_frm will close and terminate anything it was doing. but that does not happen.. only the progress_frm form closes, and i still see app_frm running with the hour glass and still running it's process/thread.
My goal is that if a user wants to abort and close the process that app_frm started, they would be able to terminate and close app_frm from progress_frm?
after the feedback below i tried the following, my form was not hitting the closing event because i copied and pasted it from another form , i then went on the design portion of progress_frm and made an event sorry for confusiong on that :( :
private void progress_frm_FormClosing(object sender, FormClosingEventArgs e)
{
Form currentForm = Form.ActiveForm;
foreach (Form frm in currentForm.MdiParent.MdiChildren)
{
if (frm.GetType() == currentForm.GetType())
{
frm.Focus();
return;
}
}
}
i get a null exception "object reference not set to an instance of an object" when the loop accesses currentForm.. remember my i am the progress_frm which is not part of the MDI config... i am trying to reference and close/terminate the child form app_frm whose parent is main_frm... i know that currentForm is main_frm, but not sure why it will not find the child form so i can reference it?? i tried changing loop to "currentForm.MdiChildren" and still got same null reference exception...
i thought i understood MDI concept, but now am getting confused on how to be able to reference them properly
Are you sure that your app_frm_temp object refers to the opened instance of app_frm Form? If it is then on FormClosing event of your app_frm you have to properly send the closing notification to your process/thread, a nice example is given here for stopping the background thread/process before closing the form: How to stop BackgroundWorker on Form's Closing event?
But before this just to make sure you are refering to correct instance of Form, this is how you can loop through all opened MDI childs and get the reference to one you are interested in:
foreach (Form frm in this.MdiParent.MdiChildren)
{
if (frm.GetType() == app_frm.GetType())
{
frm.Focus();
return;
}
}
Related
I am trying to make one windows application which contains two forms. In form1(Parent) i created one button for open second form. On that button click event i want to close form1(parent) form and open form2(child) without closing form2, but when i am press that button both forms are closed so how can I do it?
Rather than using .Close() consider using .Hide() on your parent form, this shouldn't dispose of it but rather have it hidden.
Note that exiting out of your Child form means your application won't exit. To circumvent this you should consider subscribing to the OnFormClosed event to handle the form closure.
If you look in "Program.cs" there is a form to start with.
When this form is closed, the application is terminated.
enter image description here
It should be used as a way to hide the startup form.
Even if the child form is closed with the start form hidden, the program does not end.
As #Ae774 said, you need to handle it separately.
If you want to close form1(parent) form and open form2(child) form without closing form2 by click the button, you can refer to the following code:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
Hide();
f2.ShowDialog();
Close();
}
If you want to open the parent form after the child form is closed, you can refer to this code:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
Hide();
f2.ShowDialog();
Show();
}
Here is the test result
I have program that opens subwindows inside of it (mdi.parent). I have made component that is in one window under it, however, i want that that window never actually disposed after its created because i want to keep only one instance of it.
This can be made with code:
// This prevents this window disposing from window close button, we want always show one and only
// one instance of this window.
FormClosing += (o, e) =>
{
Hide();
e.Cancel = true;
};
However, after this there is problem, closing program requires pressing close button press twice. First press closes subwindow and second terminates program. How this can be get around?
I am working with Winforms.
As Habib said, you can call Application.Exit, but:
The Form.Closed and Form.Closing events are not raised when the
Application.Exit method is called to exit your application
If this is important to you, you can do something like this (MDI parent code):
private Boolean terminating;
protected override void OnClosing(CancelEventArgs e)
{
if (!terminating)
{
terminating = true;
Close();
}
base.OnClosing(e);
}
Call Application.Exit() in the form close event.
Application.Exit - MSDN
Informs all message pumps that they must terminate, and then closes
all application windows after the messages have been processed.
The code inside of your FormClosing event handler method is a bit too terse. It does its job of preventing the user from closing the form, but as you've also noticed, it prevents you from closing the form programmatically as well.
This is easily solved by testing the value of the CloseReason property of the FormClosingEventArgs that are passed in each time the event is raised.
These will tell you the reason why the form is attempting to close. If the value is CloseReason.UserClosing, then you want to set e.Cancel to true and hide the form. If the value is something else, then you want to allow the form to continue closing.
// This prevents this window disposing when its close button is clicked by the
// user; we want always show one and only one instance of this window.
// But we still want to be able to close the form programmatically.
FormClosing += (o, e) =>
{
if (e.CloseReason == CloseReason.UserClosing)
{
Hide();
e.Cancel = true;
}
};
Use This
Form[] ch = this.MdiChildren;
foreach (Form chfrm in ch)
chfrm.Close();
You can use Application.Exit if there is no processing happening when the application is closed. Otherwise, you can check Application.OpenForms collection in MDI parent's closing event and close all the other forms that are open.
I want to prevent closing of a form in some cases. I know the usage of OnFormClosing,
but when the form is hidden (Visible==false), the OnFormClosing method is not called.
Is there a way to intercept form closing in this case?
Edit (some more details):
The form is a child in a MdiParent, should stay invisible in the background and wait for calls from another thread (by Invoke).
The MdiParent closes all child windows when the user "disconnects", in this case the above form should stay open, but invisible and still waiting for calls.
When the MidParent itself is closed, all forms should close.
Edit2 (no solution?):
It seems that there is no solution to this. My workaround now is to exclude my not-to-be-closed form in the MdiParent-code, that closes all other forms.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// This will cancel the event
e.Cancel = true;
}
Regardless of the reason, this will effectively stop a form from closing.
I have a MDI main form. On it I host a form, and I want it to show a message box before it closes (asking the user whether to save changes).
So far so good, however I have discovered that closing the MDI main form does not raise a MDI child FormClosing event. I figured I will just call MdiChild.Close() in the MDI main's FormClosing event (which does get raised). This seams to work, however it does causes a problem...
In the messagebox that I show, I offer the user to save changes, not to save changes and cancel closing. Normally this works fine, however I can't seem to find a way to cancel MDI main's FormClosing event. Is there a elegant way of doing this?
EDIT: I solved this by throwing an exception (when user decides to cancel the closing procedure) which is caught in MDI main's FormClosing event. In this way I know when I have to cancel the MDI main's FormClosing event and this seams to work fine ... However I just can't believe that this "hax" is the only way of doing this. Surely there is a better way?
I figure that you cancel the close on the childform when the user votes to cancel the close?
In that case I'd go with this Main form close
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
foreach (Form frm in this.MdiChildren)
{
frm.Close();
}
}
e.Cancel = (this.MdiChildren.Length > 0);
}
I'd suggest that instead of calling Close on the childforms you could create a method like ReadyToClose in the child forms and then the main form loops through and calls that for each of the child forms and it'll ask the question to the user and do the saving if needed and finally it'll return true if ok to continue.
And if all of the child forms "vote" for a close, then you close it all down, otherwise you close nothing.
When closing the MDI main form, all child Close events are called first so, when calling frm.Close() on the foreach loop, Close events for the child are called again (I don't know why if they should be already closed).
ho1 suggestion worked pretty well for me. Here is my modified foreach loop (ClosableMDIChildForm is an interface which contains the IsOkToClose() method):
foreach (ClosableMDIChildForm cmdif in this.MdiChildren)
{
if (!cmdif.IsOkToClose())
{
e.Cancel = true;
((Form)mdifc).Focus();
break;
}
}
Obviously, this.MdiChildren forms must implement ClosableMDIChildForm interface. The logic to decide if it's OK to close the window goes in the implementation of IsOkToClose().
Scenario
I have a C# WinForms application with a main form. I also have a button on this main form, that, when clicked, creates and displays a new form.
The problem....
...Is that I cannot click on anything on the main form when the new form is open.
The Question
How do I solve this? Is it possible to use both forms simultaneously?
Code To Launch New Form
private void barBtnStatsMonitor_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
//XtraMessageBox.Show("This Feature Has Not Been Fully Implemented Yet!");
using (StatsMonitorForm frm = new StatsMonitorForm())
{
if (frm.ShowDialog() == DialogResult.OK)
{
}
}
}
ShowDialog() opens a modal dialog.
Show() opens non-modal.
Try frm.Show instead of ShowDialog. ShowDialog opens the new form as a modal dialog so you cannot access the base form until you close this one.
when closing the main form its like closing the app...
so a suggestion would be, disable the main form close button when there are child forms open... and just enable it again when there are no child forms open...
or create a global variable(a bool perhaps), that when a child form is open.. its set to true... so when pressing the close button on the main form... it checks this variable if its true it prompts to save.. else it just closes...
ShowDialog() displays the form in MODAL mode which means you must close new form opened.
private void barBtnStatsMonitor_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
//XtraMessageBox.Show("This Feature Has Not Been Fully Implemented Yet!");
using (StatsMonitorForm frm = new StatsMonitorForm())
{
frm.Show();
//do some work here to get the dialog result some other way..
}
}