In my C# application, I have the following method that is called when the main form closes.
private void FormMain_Closing(object sender, FormClosingEventArgs e)
{
// Show this dialog when the user tries to close the main form
Form testForm = new FormTest();
testForm.StartPosition = FormStartPosition.CenterParent;
testForm.ShowDialog();
}
This creates a dialog window that will show when the main form is closing. However, my issue is that when the user closes testForm, the main form closes immediately after. I've tried all sorts of variants of e.Cancel = true; and such, and still cannot cancel the main form closing.
Any ideas?
Edit: it looks like I'm running into an issue using two ShowModal()'s in succession. Looking into the issue...
Edit: Used this.DialogResult = DialogResult.None; and it seems to have fixed my problem. It is apparently a known issue in WinForms when opening a modal dialog from a modal dialog.
This code works fine with me. I think there is a problem in another part of your code.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Form testForm = new FormTest();
testForm.StartPosition = FormStartPosition.CenterParent;
testForm.ShowDialog();
e.Cancel = testForm.DialogResult == DialogResult.Cancel;
}
This could to be handled by the children too from the docs:
If a form has any child or owned
forms, a FormClosing event is also
raised for each one. If any one of the
forms cancels the event, none of the
forms are closed. Therefore the
corresponding FormClosed events are
not sent to any of the forms.
I know that you mention in your question that you have tried to use 'e.Cancel = true;' However, the following code works in my environment (.NET 4.0, Visual Studio 2010, Windows 7):
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
// Show this dialog when the user tries to close the main form
Form testForm = new FormTest();
testForm.StartPosition = FormStartPosition.CenterParent;
testForm.ShowDialog();
e.Cancel = true;
}
If this doesn't work in your case you may have other event handlers at work. In that case try this code in a newly generated Windows Forms Application.
Related
I have another issue in converting my Winforms program to a WPF program. In my first program, I had a smaller window open to allow the user to adjust some data, and then when it closed, the other form was activated again with the new data.
I used form2.ShowDialog(); to open the form, which automatically makes the parent form deactivated in Winforms. This way when I closed form2, the parent form was activated, and I was able to use an event handler form1_Activated to reload and re-initialize some of the settings successfully.
However, now when I attempt to do the same thing with WPF, I am still able to open form2 using form2.ShowDialog();, but then when I close the form, it does not register the form1_Activated event handler. Instead, in order to reload the settings, I must click on another window, and then come back into my program to register the form1_Activated event handler.
Am I just doing something wrong, or is there another event handler that I should be using in WPF to achieve the same thing I was able to do in Winforms?
Calling ShowDialog() causes the dialog box top appear in modal mode so I don't understand why you would need an event handler to process the results after the dialog box is closed. Keep in mind that you can access public variables in the DialogBox, as well. If I understand your question, this should do what you are asking:
MainWindow:
My_DialogBox dlg = new My_DialogBox();
dlg.Owner = this;
dlg.MyPublicVariable = ''; //some value that you might need to pass to the dialog
dlg.ShowDialog(); //exection of MainWindow is suspended until dialog box is closed
if (dlg.DialogResult == true)
{
//dlg.MyPublicVariable is still accessible
//call whatever routines you need in order to refresh the main form's data
}
DialogBox:
private void OK_Button_Click(object sender, RoutedEventArgs e)
{
MyPublic variable = something; //accessible after the dialog has closed.
this.DialogResult = true;
}
private void Cancel_Button_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
The MSDN write-up on dialog boxes is pretty good. There may be some tips that might help you even more:
http://msdn.microsoft.com/en-us/library/aa969773.aspx
Good luck!
I have a main form, in the class of this form, I declare another form. This form lives with the main form until the main form is unloaded. There is a button on the main form, clicking this button will show the member form (I mentioned above). I want to prevent the member form from closing when user closes that form and I added the following FormClosing event handler for that form:
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e) {
if(e.CloseReason == CloseReason.UserClosing){
e.Cancel = true;
Hide();
}
}
That works OK for that form. However if user closes the main form, this form is not closed, and it's hidden somewhere making my application seem to run silently. I want this form also to be closed. This is very simple by adding some FormClosed event handler for my main form to close the member form manually. Closing it manually is OK, but why do I have to do that? It seems that when user closes the main form, the FormClosing event of the member form is fired with a parameter FormClosingEventArgs passed in and the CloseReason is the same as the CloseReason of the main form (which is UserClosing). I don't understand this, I thought the CloseReason of the form is UserClosing only when user clicks on the X button, I thought the CloseReason for my member form is something like "MainFormClosing".
Is there some way to close the member form automatically as by default?
UPDATE
Here is the method showing the member form (showing it as a dialog):
private void ShowMemberForm_Click(object sender, EventArgs e){
memberForm.ShowDialog();
}
But I don't think this matters, because when I load my main form, even I don't need to click on the ShowMemberForm button, and try closing my main form first, it doesn't still close the member form.
Thanks!
UPDATE
There is something strange here, I've tried commenting out the line e.Cancel = true, or even all the FormClosing event handler and the problem is still there. This is so strange, it works OK before, I've just added the member form and this form relates to some Thread handling, but the thread starts only when a button on the member form is clicked. I didn't click that button.
What I have done in the past is set a flag when programatically closing
so in the MemberForm
private bool _ForceClose = false;
public void ForceClose()
{
_ForceClose = true;
this.Close();
}
private void MemberForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(!_ForceClose)
{
e.Cancel = true;
Hide();
}
}
Then in your MainForm you can call
memberForm.ForceClose();
From within your MainForms FormClosing method or from your MainForms Dispose() or Deconstructor.
It's low tech, but it works. Im not sure if you should put _ForceClose = true in your MemberForm's Dispose method, i'm fairly certain when it gets there its already been closed BUT it couldn't really hurt.
This is the code in question:
private void FormAccounting_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.FormAccountingLocation = this.Location;
Properties.Settings.Default.Save();
if (IsEditing)
{
MessageBox.Show("Please save or cancel open transactions before closing the accounting window.", "Open Transactions", MessageBoxButtons.OK, MessageBoxIcon.Information);
e.Cancel = true;
}
}
I've added breakpoints to the e.Cancel = true; line to ensure it's being executed.
The form closes immediately after clicking Ok.
Here's the code that calls FormAccounting:
private void buttonAccounts_Click(object sender, EventArgs e)
{
FormAccounting NewFormAccounting = new FormAccounting();
NewFormAccounting.Show();
}
Canceling the form close event works to prevent:
User closing the form
Application.Exit from exiting the application
Code from calling Form.Close on the form
But it does not work to prevent:
User closing application's main form
Code calling Form.Dispose on the form
Code calling Form.Close on the application's main window
The last 3 cases don't even trigger the form close event on the non-main form, so the form goes away without a chance to cancel it. Perhaps your application is causing the form to first close in one of the first 3 ways, which triggers the event, and then in one of the second 3 ways (or something similar), which does not trigger the event and forces the form closed anyway.
Edit:
Add this function to your form's code and it will allow you to review in the debugger what the call stack looks like when your window is getting closed so you can see what is actually causing it:
protected override void DestroyHandle()
{
System.Diagnostics.Debugger.Break();
base.DestroyHandle();
}
I am using Visual Studio 2010, C# .NET 4.0. I have 3 forms: Form1, Form2, Form3.
In Form1 I have a button to open Form2:
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
}
In Form2 I have a private Form3 variable always pointing to the same Form3:
private Form3 f = new Form3();
And a button to open it as a dialog:
private void button1_Click(object sender, EventArgs e)
{
f.ShowDialog();
}
In Form3 I just have a button to hide the form:
private void button1_Click(object sender, EventArgs e)
{
this.Hide();
}
The problem is that having the situation that Form2 is in front of Form1, and Form3 in front of Form2, when I click the button of Form3 to hide it, it not only hides itself but sends Form1 to the back of all of the other Windows.
This only happens when there is a window of another program (such as Windows Explorer) in the background of Form1. It seems like a bug. What do you think?
Yes, this cannot work properly by design. A dialog disables all of the windows that your program displays. So that it is modal. When you hide the dialog, there are no windows left that can get the focus. Windows is forced to find another window to give the focus to. That will be a window owned by another application. Your own windows will now hide behind it.
There are more side effects, the dialog will also close. Necessary because otherwise the user can never get back to your program anymore since all windows are disabled. This is all unsurprising behavior. Bug would be a strong word, but it would of course work better if it first re-enabled all windows before closing the dialog. But closing the dialog is already undesirable behavior.
Don't call Hide() for a dialog. Just set the DialogResult property to DialogResult.Cancel to achieve the exact same effect, minus the focus problem. You do have to reset it back to None if you want to display the dialog again. That's a real bug.
By the documentation. Form.Close method doesn't dispose forms shown by Form.ShowDialog method. Quote:
The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.
So, maybe there are ways to return focus to your application (e.g. via Windows API). But it is much more convenient to call Form.Close manually on dialog windows.
I'm encountering strange behavior with forms on a c# 3.5 app. On a button click, my form1 hides itself, creates a new form2, and shows form2. Form1 also contains the event method triggered when form2 closes. Here's the code inside Form1:
Form2 form2;
void button1_Click(object sender, EventArgs e)
{
this.Hide();
form2 = new form2();
form2.Show();
form2.FormClosed += new FormClosedEventHandler(form2_FormClosed);
}
void form2_FormClosed(object sender, FormClosedEventArgs e)
{
form2.Dispose();
form2 = null;
this.Show();
}
Now, my problem is that sometimes when I open form2 (hiding form1), or when I close form2 (showing form1), the new form will come up on the screen for a blink and then hide itself. It's still open and I can click it from the taskbar to show it again, but the window itself is sent behind any other open windows. It looks like it opens up but minimizes instantly.
This behavior occurs randomly. Sometimes forms will open up and hide without a problem, but sometimes they'll lose focus over another window. I've tried using focus(), activate(), and topmost but all have failed to prevent the sudden hiding.
Does anyone know why is this happening and how to fix it?
Thanks.
You hide your form too soon. For a brief moment, your app has no window that can contain the focus. That forces Windows to go hunting for another window to give the focus to, it will pick one from another application. That window will now be the foreground window, your second form will not get the focus and appear lower in the Z-order. The fix is simple:
void button1_Click(object sender, EventArgs e)
{
form2 = new form2();
form2.Show();
form2.FormClosed += new FormClosedEventHandler(form2_FormClosed);
this.Hide(); // Moved
}