Prevent Closing Event Firing when calling Shutdown() - c#

I have created a WPF application, that is designed to run in the background and uses an icon in the system tray.
To achieve this goal, I have attached the following method to the Closing event of the MainWindow otherwise it closes. Also to note in the App.xaml I have set the ShutdownMode to OnExplicitShutdown
private void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
The problem I am facing is that on the Context Menu of the System Tray Icon I have an Exit button which calls
App.Current.Shutdown();
This causes the Closing event to fire again and display the notification, which I do not want to do. How can I prevent this event firing again?
Or is this not possible and will I have to use a boolean variable called ShuttingDown to handle it and check this variable before displaying the notification?

on window closing, the app can either be actually just fine (clicking X on the window), or really force closing (from the context menu).
one way to do this is the way you're looking for, essentially "when the context menu is clicked to 'force close' the app, remove the window event handler before calling App.Current.Shutdown()".
private void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MainWindow.Closing -= Window_Closing;
App.Current.Shutdown();
}
another way to do this is to track if we're force closing the app, essentially "when the context menu is clicked to 'force close' the app, set a 'force close' flag to true so that the window knows we're actually closing for real and to not do the minimizing stuff."
this means there should be a flag in scope of both the window and the context menu. this flag would be initialized as false, considering that there will only ever be 1 force close, which will be when the app ends.
i'll call the flag _IsForceClosing. it's naturally initialized to false.
bool _IsForceClosing;
private void Window_Closing(object sender, CancelEventArgs e)
{
if (_IsForceClosing)
return; //don't do the hiding stuff, we're really closing
e.Cancel = true;
this.Hide();
//This method simply displays a notification to the user that the app is still running in the system tray.
DisplaySysTrayNotification();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
_IsForceClosing = true;
App.Current.Shutdown();
}

Related

Closing a window throws a InvalidOperationException

I have a window in which I handle the Closing event in a custom function. In the XAML I have set the following:
<ext:ExtendedWindow x:Name="Window1" Closing="Window_Closing">
This function is declared in the code-behind as follows:
private void Window_Closing(object sender, CancelEventArgs e)
{
Closing -= Window_Closing;
e.Cancel = true;
Storyboard storyboard = this.CloseWindowWidthAnimation(0f);
storyboard.Completed += CloseWindow;
storyboard.Begin();
}
private void CloseWindow(object sender, EventArgs e)
{
this.Close();
}
Window_Closing cancels the closing event and plays an animation on the window (width shrinks to 0). To the Completed event I add a function that finally closes the window after the animation has played. CloseWindowWidthAnimation is a static method in a helper class that just returns a storyboard. The ExtendedWindow has a base class of Window and only has a few dependencyproperties to handle color schemes.
When the Close function is done executing and Just My Code is enabled, the 'break mode' screen pops up. Continuing the debugging session exits the application, but I think this is a known issue. When Just My Code is disabled, the following error shows:
This Visual is not connected to a PresentationSource.
The error shows when the window has in fact been closed after CloseWindow exits. I do think it has something to do with the storyboard/animation, since it does not throw the error when I don't override the Closing event. When I build the app and run the executable, it doesn't crash and I don't catch the error somewhere. I'm thinking it has something to do with the storyboard, but the error isn't very descriptive and I haven't been able to find anything on this. So my question is as follows:
What might cause this type of behaviour? What could I possibly do to fix this?
Update: Call Stack window (Main thread)

Application.Exit() not working properly

I have a separate windows form for user to select background music and it will always stay there unless the application is closed. I prevented the user from closing the music form by using the code:
private void Music_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
and in my main Program.cs i run a page called login like so:
Application.Run(new Login());
I also have a FormClosed event in all my forms that closes the whole program after pressing the cross
private void Login_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
However, after i add the code that the user is not able to close the music form, my application is only able to exit by pressing the cross when it is in the login page, which is the start of the program ran by the main page (the application used to be able to exit in all of my forms by pressing the cross)
I want to know if there is any way for me to properly exit my application or a way to make user not able to close the music form without affecting my other form's closing. Thank you
The code inside Music_FormClosing is preventing your application from exiting. To get the desired behavior (prevent the user closing the music form), you can utilize the FormClosingEventArgs CloseReason property:
private void Music_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
e.Cancel = true;
}

Need to detect early when a WinForms application is closing before it closes any child windows

I have a winforms C# application with multiple MDI child windows, each of which can contain changed user data.
When a child window is closed individually, the user is warned about the changed data, which works fine.
However, if the user attempts to close the application, I only want to warn once for all child windows if any have changed data (the data is not that critical).
So the idea is to hook into the main window's OnClosing event, look for changed user data in any of the child windows, display a warning just once if I find any changed data, and set a boolean to prevent each child window from bothering the user multiple times.
The problem I'm seeing is, the OnClosing event for the main window is triggered AFTER the OnClosing events for each child window are triggered, so I can't set my boolean soon enough.
Is there an event for application closing that I can hook into that arrives sooner than OnClosing, or is there maybe a Windows message I can trap?
Instead of hooking into MDI parent form close messages and setting flags, you can make your child forms subscribe to FormClosing event and skip the processing if FormClosingEventArgs.CloseReason is MdiFormClosing:
private void ChildForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.MdiFormClosing) return; // Do nothing
// ...
}
Solved it, I just needed to hook into the WM_CLOSE Windows message:
protected override void WndProc(ref Message m)
{
// Crucially, this message arrives before my child windows get the OnClosing event.
if (m.Msg == WM_CLOSE)
{
// So I set my boolean here and everything works great.
}
base.WndProc(ref m);
}
I would create a boolean in each of your sub-windows that dictates whether or not to open the prompt.
public bool Prompt = true;
private void Form_Closing(object sender, EventArgs e)
{
if (Prompt)
{
MessageBox.Show("Data thingy...whatever");
}
}
And then in your main form you can set this boolean to false.
private void MainForm_Closing(object sender, EventArgs e)
{
form1.Prompt = false;
form1.Close();
form2.Prompt = false;
form2.Close();
//etc
}

How to close C# process?

I wrote a simple program using Visual Studio(C#). When I close my program(click at Х) the form is closed, but the process remains. I had to close it from Task Manager.
What is the command to close process?
My code:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
e.Cancel = true; means stop the form from closing. That's the main issue with your code.
You should use this parameter if you have a confirmation something like "Are you sure you want to close?" if the user selects "No" you set e.Cancel to true.
Just remove that code (or set Cancel to false) and your form will close, and if that's the last one of your application, it will end.
So the final solution for your problem is a simple
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
The e.Cancel=true will prevent your form from closing, so remove it.
if it still doesn't work, try this :
use the Application.Exit() method on the FormClosed event instead of FormClosing:
To do this, go into your form designer window : press maj + F7 or right click on your form in your solution explorer and click on Form designer (something like that)
Right Click on your Form, Select Properties, display the Events, then double-click on the Form Closed event and the designer will automaticaly register the event and generate your code.
You should have something like this without the Application.Exit() method generated :
private void Form1_FormClosed(object sender, FormClosingEventArgs e)
{
Application.Exit();
}

How to Disable Alt + F4 closing form?

What is the best way to disable Alt + F4 in a c# win form to prevent the user from closing the form?
I am using a form as a popup dialog to display a progress bar and I do not want the user to be able to close it.
This does the job:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
Edit: In response to pix0rs concern - yes you are correct that you will not be able to programatically close the app. However, you can simply remove the event handler for the form_closing event before closing the form:
this.FormClosing -= new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
this.Close();
If you look at the value of FormClosingEventArgs e.CloseReason, it will tell you why the form is being closed. You can then decide what to do, the possible values are:
Member name - Description
None - The cause of the closure was not defined or could not be determined.
WindowsShutDown - The operating system is closing all applications before shutting down.
MdiFormClosing - The parent form of this multiple document interface (MDI) form is closing.
UserClosing - The user is closing the form through the user interface (UI), for example by clicking the Close button on the form window, selecting Close from the window's control menu, or pressing ALT+F4.
TaskManagerClosing - The Microsoft Windows Task Manager is closing the application.
FormOwnerClosing - The owner form is closing.
ApplicationExitCall - The Exit method of the Application class was invoked.
I believe this is the right way to do it:
protected override void OnFormClosing(FormClosingEventArgs e)
{
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
break;
}
base.OnFormClosing(e);
}
Note that it is considered bad form for an application to completely prevent itself from closing. You should check the event arguments for the Closing event to determine how and why your application was asked to close. If it is because of a Windows shutdown, you should not prevent the close from happening.
You could handle the FormClosing event and set FormClosingEventArgs.Cancel to true.
I am using a form as a popup dialog to display a progress bar and I do not want the user to be able to close it.
If the user is determined to close your app (and knowledgeable) enough to press alt+f4, they'll most likely also be knowledgeable enough to run task manager and kill your application instead.
At least with alt+f4 your app can do a graceful shutdown, rather than just making people kill it. From experience, people killing your app means corrupt config files, broken databases, half-finished tasks that you can't resume, and many other painful things.
At least prompt them with 'are you sure' rather than flat out preventing it.
This is a hack to disable Alt + F4.
private void test_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.ModifierKeys == Keys.Alt || this.ModifierKeys == Keys.F4)
{
e.Cancel = true;
}
}
Subscribe FormClosing event
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = e.CloseReason == CloseReason.UserClosing;
}
Only one line in the method body.
This does the job:
bool myButtonWasClicked = false;
private void Exit_Click(object sender, EventArgs e)
{
myButtonWasClicked = true;
Application.Exit();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (myButtonWasClicked)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
Would FormClosing be called even when you're programatically closing the window? If so, you'd probably want to add some code to allow the form to be closed when you're finished with it (instead of always canceling the operation)
Hide close button on form by using the following in constructor of the form:
this.ControlBox = false;

Categories