如何区分收处理程序“窗口的关闭按钮点击(X)”对window.close()的(How to dis

2019-07-03 18:52发布

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

  • 用户在窗口的右上角按(X)按钮或
  • window.close()的已通过编程调用。

我想在window.Closing处理程序来检测这一点。 我可以设置)的标志,每当我打电话window.Close(,但这不是一个非常漂亮的解决方案。

Answer 1:

我不知道我喜欢这个根本,但它是你明明有问原因的问题。 如果你拿一个堆栈跟踪在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);
}


Answer 2:

所不同的是以下几点:

window.close()的原因WM_CLOSE被发送到窗口。

ALT + F4和X按钮原因WM_SYSCOMMAND与SC_CLOSE类型的消息。 如果你想航线此消息还可以决定(并最终导致WM_CLOSE)。

这里有一段代码捕获此消息。 如果你想取消默认行为从代理返回“真”:

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;
    }
}


文章来源: How to distinguish 'Window close button clicked (X)' vs. window.Close() in closing handler
标签: wpf window