【问题标题】:How to distinguish 'Window close button clicked (X)' vs. window.Close() in closing handler如何区分“单击的窗口关闭按钮 (X)”与关闭处理程序中的 window.Close()
【发布时间】:2012-11-13 13:04:47
【问题描述】:

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

  • 用户按下窗口右上角的 (X) 按钮或
  • window.Close() 已被程序调用。

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

【问题讨论】:

  • 虽然有可能,但将它们区别对待似乎不是一个好主意。从用户体验的角度来看,Alt-F4/File->Exit/Closing with close button/closures以编程方式应该都是一样的..
  • 我认为当您使用关闭按钮来隐藏子窗口时这是有道理的,但喜欢在按下应用程序关闭按钮时关闭子窗口。

标签: wpf window


【解决方案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);
}

【讨论】:

    【解决方案2】:

    区别如下:

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

    Alt+F4 和 X 按钮会导致带有 SC_CLOSE 类型的 WM_SYSCOMMAND 消息。您可以决定是否希望进一步路由此消息(并最终导致 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 2012-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多