如何区分"单击窗口关闭按钮 (X)"与窗口。关闭处理程序中的 close()



有没有一种聪明的方法来检测窗口是否被关闭

  • 用户按下窗口右上角的 (X) 按钮或
  • 窗。Close() 以编程方式调用。

我想在窗口中检测到这一点。关闭处理程序。每当我调用窗口时,我都可以设置一个标志。Close(),但这不是一个非常漂亮的解决方案。

我不确定我是否喜欢这个,但这是一个你显然有理由问的问题。 如果要在 OnClosing 事件中进行堆栈跟踪,则可以查找 Window.Close 事件。

protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
   bool wasCodeClosed = new StackTrace().GetFrames().FirstOrDefault(x => x.GetMethod() == typeof(Window).GetMethod("Close")) != null;
   if (wasCodeClosed)
   {
       // Closed with this.Close()
   }
   else
   {
       // Closed some other way.
   }
   base.OnClosing(e);
}

区别如下:

Window.Close() 使WM_CLOSE被发送到窗口。

Alt+F4 和 X 按钮会导致WM_SYSCOMMAND SC_CLOSE类型的消息。您可以决定是否要进一步路由此消息(并最终导致WM_CLOSE)。

下面是一段用于捕获此消息的代码。如果您希望取消默认行为,请从委托返回"True":

class SystemMenu : IDisposable
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_CLOSE = 0xF060;
    public delegate bool HandleSystemCommand();
    HwndSource _source;
    HandleSystemCommand _handler;
    public SystemMenu(Window window, HandleSystemCommand handler )
    {
        _handler = handler;
        _source  = HwndSource.FromHwnd(new WindowInteropHelper( window ).Handle);
        _source.AddHook(WndProc);
    }
    public void Dispose() {
        _source.RemoveHook(WndProc);
    }
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case WM_SYSCOMMAND:
                int command = wParam.ToInt32() & 0xfff0;
                if (command == SC_CLOSE)
                    handled = _handler();
                break;
            default:
                break;
        }
        return IntPtr.Zero;
    }
}

最新更新