When clicking right-topmost Close button, the window is closed and developer can cancel window close in window's Closing event handler by settting e.Cancel to true. Here is a callstack example when the Close button is clicked. Alt-F4 has the same effect as clicking Close button.
Console.MainWindow.WindowConsole_Closing(object sender, System.ComponentModel.CancelEventArgs e) Line 679 C# PresentationFramework.dll!System.Windows.Window.OnClosing(System.ComponentModel.CancelEventArgs e) + 0x8c bytes PresentationFramework.dll!System.Windows.Window.WmClose() + 0x96 bytes ............. WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc1 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes Mitutoyo.QCCAT.Console.exe!Mitutoyo.QCCAT.Console.App.Main() + 0x5e bytes Unknown
If a user doubleclicks leftmost application icon, the application initiates app shutdown and send window close signals to all windows. But, if window close event handler cancels, it will not be honored and simply ignored and keep going for shutdown. This means develoepr cannot cancel window close, no matter what. Here is the call stack when app icon is doubleclicked. You can see Application.DoShutdown() in the middle.
> Console.MainWindow.WindowConsole_Closing(object sender, System.ComponentModel.CancelEventArgs e) Line 679 C# PresentationFramework.dll!System.Windows.Window.OnClosing(System.ComponentModel.CancelEventArgs e) + 0x8c bytes PresentationFramework.dll!System.Windows.Window.WmClose() + 0x96 bytes PresentationFramework.dll!System.Windows.Window.InternalClose(bool shutdown, bool ignoreCancel) + 0xa1 bytes PresentationFramework.dll!System.Windows.Application.DoShutdown() + 0x1b6 bytes PresentationFramework.dll!System.Windows.Application.ShutdownImpl() + 0x1c bytes PresentationFramework.dll!System.Windows.Application.ShutdownCallback(object arg) + 0x5 bytes ........... [Managed to Native Transition] WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc1 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes Mitutoyo.QCCAT.Console.exe!Mitutoyo.QCCAT.Console.App.Main() + 0x5e bytes Unknown
One can work around this problem by overwriting Applications.Close behavior. Here is a code snippet.
public partial class MainWindow : RibbonWindow { public MainWindow() { InitializeComponent(); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, ApplicationCloseExecuted)); } private void ApplicationCloseExecuted(object sender, ExecutedRoutedEventArgs e) { this.Close(); } private void Window_Closing(object sender, CancelEventArgs e) { if (MsgBox("Sure?") == true) { Terminate(); } else { e.Cancel = true; // cancel window close } } }