I have an event handler subscribed to the FormClosing event. This event handler provides dialog for the user when they exit my application; like so:
private void frmUavController_FormClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
DialogResult dlgResult = MessageBox.Show("Are you sure you want to exit?", "Exit?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dlgResult == DialogResult.Yes)
{
UtilSTKScenario.PauseScenarioAnimation(UtilSTKScenario._stkObjectRoot);
}
else if (dlgResult == DialogResult.No)
{
e.Cancel = true;
}
}
Because the application runs in a side-by-side fashion; injecting COM commands into another application - I want my application to exit if the application receiving COM commands is not launched (or closed during execution). This is achieved like so:
static UtilSTKScenario()
{
// give time for active form to show
Thread.Sleep(100);
_stkProgramId = ConfigurationManager.AppSettings.Get("stkProgramId");
if (CheckIfStkIsLaunched())
{
InitAllFields();
}
else
{
HideController dHideController = new HideController(((frmUavController)Form.ActiveForm).HideControllerUi);
((frmUavController)Form.ActiveForm).Invoke(dHideController);
Application.Exit();
}
}
Calling 'Application.Exit()' causes the FormClosing event to fire. This I do not want - rather, I want the application to just exit.
Any ideas ?
WulfgarPro
You might be able to look at the event args of the FormClosing event. FormClosingEventArgs has a CloseReason property that may give an indicator if the form was closed by a user directly as opposed to some other mechanism.
Though I'm not clear how Application.Exit() calls will appear... If it is also showing as CloseReason.UserClosing then you may need to add an overload to your form [e.g. SystemClose()] to close your form and use an instance variable to tell it not to prompt within your handler.
Your FormClosing event gets a FormClosingEventArgs parameter, which has a CloseReason property. If that's CloseReason.ApplicationExitCall, then the form is closing because of a call to Application.Exit. You can just skip your "close?" prompt in that case.
private void frmUavController_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.ApplicationExitCall)
return;
// ...
The typical way to handle this sort of thing (bypass normal "do you want to close?" checks) is to use a Boolean variable. Name it something like _forceExit, set it to true if the external event forces you to close, and if it's true, skip the dialog box in your Closing event.
Can you look at the sender object? My guess is that the sender object is different depending on you actually close the form or call the Application.Exit() method.
Related
I made multi languages c# application that will switch the language
when user change Language the application must restart in order for the application change the language
now I have one question and one problem
Is there away to change the language without restarting the application ?
a problem showup when Application.Restart(); executed the Formclosing event raised too as shown below and as result the application will not restart
and will promet for the exit message and close if Yes and will a lanche another copy of the application with new language without closing the old one
now.. Is there away the so the Formclosing event not executed in that case only ? or better to have away as I mentioned ad point 1 above.
private void F0100_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result;
result = MessageBox.Show("Are sure you want to exit?", "Message", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, MessageBoxOptions.RtlReading);
if (result == DialogResult.Yes)
{
Environment.Exit(1);
}
else
{ e.Cancel = true; }
}
If your problem is just to avoid giving the user the possibility to stop the closing when you execute the call to Application.Restart, then all you need to do is to look at the CloseReason passed to your Form_Closing event handler
private void F0100_FormClosing(object sender, FormClosingEventArgs e)
{
// Do not prompt the user if we have called Application.Restart
if(e.CloseReason != CloseReason.ApplicationExitCall)
{
DialogResult result;
....
}
}
When closing form, FormClosed event occurs, and I want to put some work when FormClosed event occurs like:
this.FormClosed += (s, e) => {
var result = MessageBox.Show("Exit Program?", "Exit?", MessageBoxButtons.YesNo, MessageBoxIcons.Question);
if (result == DialogResult.No) {
return;
} else {
// Do some work such as closing connection with sqlite3 DB
Application.Exit();
}
};
The problem is that no matter I choose yes or no in the messagebox, the program gets closed. I need to abort program exit if I choose no, so how do I do that?
The FormClosing (as opposed to your FormClosed) event's FormClosingEventArgs contains a Cancel boolean that you can change to true. Note that this will occur even if you close the form programmatically.
this.FormClosing += (s, e) => {
var result = MessageBox.Show("Exit Program?", "Exit?", MessageBoxButtons.YesNo, MessageBoxIcons.Question);
if (result == DialogResult.No) {
e.Cancel = true;
} else {
// Do some work such as closing connection with sqlite3 DB
Application.Exit();
}
};
To determine how the form was closed, it also includes a CloseReason.
See docs here and here.
You can't use the FormClosed event, you need to use the FormClosing event and set e.Cancel to true.
The reason for that is that the FormClosed event occurs after the form has been closed, while the FormClosing event occurs as the form is being closed.
The FormClosingEventArgs class contains a boolean property called Cancel that you can set to true to stop the form from being closed.
I am working on a C#-based utility that makes use of the FormClosing event, and the event is supposed to do different things depending on whether the form was closed programatically through the form.Close(); method, or by anything else (user clicking the X, program exiting, etc.)
The FormClosingEventArgs in the FormClosing event have a property called CloseReason (of enum type CloseReason).
CloseReason could be: None, WindowShutDown, MdiFormClosing, UserClosing, TaskManagerClosing, FormOwnerClosing, ApplicationExitCall.
Ideally, there would be a way to distinguish between when the user clicks the red X, and when the Close(); method is called (through the clicking of a Continue button after other actions are performed). However, the CloseReason property in FormClosingEventArgs is set to UserClosing in both cases, so there is no way to distinguish between when the user closes the form intentially, and when the form is programmatically closed. This goes contrary to my expectation that CloseReason would equal None if the Close() method is invoked arbitrarily.
//GuideSlideReturning is an cancelable event that gets fired whenever the current "slide"-form does something to finish, be it the user clicking the Continue button or the user clicking the red X to close the window. GuideSlideReturningEventArgs contains a Result field of type GuideSlideResult, that indicates what finalizing action was performed (e.g. continue, window-close)
private void continueButton_Click(object sender, EventArgs e)
{ //handles click of Continue button
GuideSlideReturningEventArgs eventArgs = new GuideSlideReturningEventArgs(GuideSlideResult.Continue);
GuideSlideReturning(this, eventArgs);
if (!eventArgs.Cancel)
this.Close();
}
private void SingleFileSelectForm_FormClosing(object sender, FormClosingEventArgs e)
{ //handles FormClosing event
if (e.CloseReason == CloseReason.None)
return;
GuideSlideReturningEventArgs eventArgs = new GuideSlideReturningEventArgs(GuideSlideResult.Cancel);
GuideSlideReturning(this, eventArgs);
e.Cancel = eventArgs.Cancel;
}
The issue with this is that when the Close(); method is invoked after the event GuideSlideReturning finishes without being canceled, the FormClosing event handler is unable to tell that the form was closed through the method instead of being closed by the user.
What would be ideal is if I could define what the FormClosing event's FormClosingEventArgs CloseReason would be, like this:
this.Close(CloseReason.None);
Is there a way to do this? The form.Close(); method does not have any overloads that accept any parameters, so is there a variable I can set or an alternate method I can call?
Set a flag before calling close programmatically. This can be wrapped up in a private method:
private bool _programmaticClose;
// Call this instead of calling Close()
private void ShutDown()
{
_programmaticClose = true;
Close();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing();
_programmaticClose = false;
}
Is it possible? I need to call the Form1_FormClosing here:
ContextMenu trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Close", delegate {
Form1_FormClosing(????)
});
I need it because I'm using the CancelEventArgs from _FormClosing event:
private void Form1_FormClosing(object sender, CancelEventArgs e)
{
if (th != null && th.ThreadState == System.Threading.ThreadState.Running)
{
if (MessageBox.Show("the process is running, you want stop it?", "app", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
AbortProccess(); }
else
{
e.Cancel = true;
}
}
}
I hope this is clear,thanks in advance.
There are a few things you could do.
First, you could just close the form using myForm.Close() as this will indirectly call the FormClosing event. Also, you could move everything within the FormClosing event into a separate method instead of in the event itself. You can then call that method from the event and from your MenuItem. If you don't want to do either of those, you could try using this as the delegate:
//CancelEventArgs can also take a boolean which dictates if
//it should be cancelled
Form1_FormClosing(this, new CancelEventArgs());
This is technically possible, just call the OnFormClosing() method. But that doesn't actually close the form, it should only ever run when the form actually closes. Pretending that the form is closing when it is not actually closing is going to lead to disappointment.
So just call the Close() method instead.
ContextMenu trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Close", delegate {
this.Close();
});
Im playing about with some very simple windows forms. I have an event handler for a form close event that asks the user whether they want to save what they've typed:
private void closeNpForm(object sender, FormClosingEventArgs e)
{
if (!saveFlag)
{
if (MessageBox.Show("Do you want to save the text entered?", "Save Changes?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = true;
saveFlag = true;
writeToFile(this.allText.Text);
}
}
}
if the user clicks yes (indicating they do want to save their text) i call the writeToFile method, and also set a flag so as not to ask them to save again:
private void writeToFile(string text)
{
writer = new StreamWriter("inputdata.txt");
writer.Write(text);
writer.Close();
this.Close();
}
As far as i can see, the writeToFile method should close the form when its finished. But this isnt happening, when i run the writeToFile method, the form just stays open. Can anyone tell me what im doing wrong?
as i understand it, calling this.Close() should trigger a form closing event, calling my event handler, due to the flag now being true, the form should just close without a problem.
note, my parent class extends the Form class, so im just using this to refer to my form instance.
e.Cancel = true -- whoops. The event is told cancel (read: not close the window).
I suspect that because close() is being called from within the close event and there is some internal clobbering going on (either suppressed or the Cancel is propagated over, etc). Just clean up the code (saving to the file has nothing to do with closing the window although the file might be saved and the window closed from within a button event.)
Happy coding.
writing to file and closing the form are two different kinds of operations. you should not have this.Close() in your writeToFile method.
As pst says, by setting e.cancel to true, you are basically telling the CloseForm event to be cancelled, therefore it's not closing once it exits from the closeNpForm event handler.
After exiting closeNpForm, the form checks for the Cancel property of the event and will not actually proceed with closing itself.
Why are you cancelling the close event and then calling writeToFile that closes the form?
In addition to what #pst said, why are you setting Cancel = true if you don't want to cancel the closing of the form?
If you remove e.Cancel = true; and this.Close(); it should do what you want.
This works for me:
public class Form1 : Form
{
bool saveFlag;
private void Form1_Load(object sender, EventArgs ev)
{ FormClosing += closeNpForm;
}
private void closeNpForm(object sender, FormClosingEventArgs e)
{
if (!saveFlag)
{
if (MessageBox.Show("Do you want to save the text entered?", "Save Changes?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = true;
saveFlag = true;
this.Close();
}
}
}
}