处理来自 Icon 的应用程序关闭调用

Joh*_*ohn 5 c# wpf prism

我在主窗口上添加了用于关闭事件的代码,该代码适用于单击 X,并且能够毫无问题地取消事件(它通过“您确定吗?确保保存”类型的对话框运行,并且闭幕式活动)

不幸的是,如果我双击该图标,它会遇到事件断点RibbonWindow_Closing,但是当e.Cancel设置为 true 时,它​​无论如何都会关闭,就好像它被调用一样Application.Current.Shutdown()

Alt-F4(和图标 -> 关闭)和 X 按钮均已正确处理,但未双击图标本身

有谁知道为什么会发生这种情况?我正在使用 Prism,如果重要的话,主窗口是由引导程序创建的。

这是堆栈跟踪,除了点击我的 RibbonWindow_Closing 事件之外,它是所有外部代码:

MyProgram.exe!MyProgram.Shell.RibbonWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) Line 64  C#
 PresentationFramework.dll!System.Windows.Window.OnClosing(System.ComponentModel.CancelEventArgs e) + 0x91 bytes    
Run Code Online (Sandbox Code Playgroud)

PresentationFramework.dll!System.Windows.Window.WmClose() + 0x96 bytes  
    PresentationFramework.dll!System.Windows.Window.WindowFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xe5 bytes 
 PresentationCore.dll!System.Windows.Interop.HwndSource.PublicHooksFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x7e bytes    
 WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xbe bytes   
 WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7d bytes   
 WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes    
 WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes   
 WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xb4 bytes   
 WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x104 bytes   
 [Native to Managed Transition] 
 [Managed to Native Transition] 
 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  
    WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
 WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes   
 WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0x8d bytes 
Run Code Online (Sandbox Code Playgroud)

测试 RibbonWindow,给出消息但仍然关闭

<ribbon:RibbonWindow x:Class="MyProject.TestShell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
        Title="TestShell" Height="300" Width="300" Closing="Window_Closing">
    <Grid>
        <DockPanel LastChildFill="True">
        </DockPanel>
    </Grid>
</ribbon:RibbonWindow>
Run Code Online (Sandbox Code Playgroud)

这与常规窗口一样,获取消息并保持打开状态:

<Window x:Class="MyProject.TestShell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TestShell" Height="300" Width="300" Closing="Window_Closing">
    <Grid>
        <DockPanel LastChildFill="True">
        </DockPanel>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

背后的代码很简单:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    e.Cancel = true;
    MessageBox.Show("No close!");
}
Run Code Online (Sandbox Code Playgroud)

更新

好的,我将其范围缩小为 RibbonWindow 控件的问题,显然,双击图标时它会关闭应用程序。

显然,如果以相同的方式关闭子窗口,它也会关闭主应用程序:http://social.msdn.microsoft.com/Forums/en/wpf/thread/3e9cdc9c-dfb7-49f2-923a-ead07504d568

/// <summary>
///   This handles the click events on the window icon.
/// </summary>
/// <param name="sender">Click event sender</param>
/// <param name="e">event args</param>
private void IconMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (e.ClickCount == 1)
    {
        if (SystemCommands.ShowSystemMenuCommand.CanExecute(null, this))
        {
            SystemCommands.ShowSystemMenuCommand.Execute(null, this);
        }
    }
    else if (e.ClickCount == 2)
    {
        if (ApplicationCommands.Close.CanExecute(null, this))
        {
            ApplicationCommands.Close.Execute(null, this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ohn 2

好的,我将其范围缩小为 RibbonWindow 控件的问题,显然,双击图标时它会关闭应用程序。

http://social.msdn.microsoft.com/Forums/en/wpf/thread/3e9cdc9c-dfb7-49f2-923a-ead07504d568

/// <summary>
///   This handles the click events on the window icon.
/// </summary>
/// <param name="sender">Click event sender</param>
/// <param name="e">event args</param>
private void IconMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (e.ClickCount == 1)
    {
        if (SystemCommands.ShowSystemMenuCommand.CanExecute(null, this))
        {
            SystemCommands.ShowSystemMenuCommand.Execute(null, this);
        }
    }
    else if (e.ClickCount == 2)
    {
        if (ApplicationCommands.Close.CanExecute(null, this))
        {
            ApplicationCommands.Close.Execute(null, this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里找到了解决方案:http://social.msdn.microsoft.com/Forums/en/wpf/thread/9955b191-13d5-4986-a5c0-e73f50a44b44

这是注册我自己的 ApplicationClosing 命令,例如:

[Export]
public partial class TestShell : RibbonWindow
{
    public TestShell()
    {
        InitializeComponent();

        CommandManager.RegisterClassCommandBinding(typeof(TestShell), new CommandBinding(ApplicationCommands.Close, CloseApplicationExecuted));
    }

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        e.Cancel = true;
        MessageBox.Show("Not closing 1!");
    }

    private static void CloseApplicationExecuted(object sender, ExecutedRoutedEventArgs args)
    {
        RibbonWindow window = sender as RibbonWindow;
        if (window != null)
        {
            MessageBox.Show("Not closing 2!");
            args.Handled = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我双击该图标,我会得到“未关闭 2!”,而任何其他关闭方法我都会得到“未关闭 1!”

希望这可以节省我解决问题所需的时间。感谢汉斯帮助我诊断问题。

更新:如果您希望 CloseApplicationExecuted 触发与常规关闭相同的事件,只需调用

private static void CloseApplicationExecuted(object sender, ExecutedRoutedEventArgs args)
    {
        RibbonWindow window = sender as RibbonWindow;
        if (window != null)
        {
            args.Handled = true;
            window.Close();
        }
    }
Run Code Online (Sandbox Code Playgroud)