How to distinguish 'Window close button clicked (X)' vs. window.Close() in closing handler

前端 未结 2 1231
旧巷少年郎
旧巷少年郎 2020-12-19 02:03

Is there a clever way to detect whether a window was closed by

  • A user pressing the (X) button in the upper right corner of the window or
  • window.Close(
相关标签:
2条回答
  • 2020-12-19 02:43

    The difference is the following:

    Window.Close() causes WM_CLOSE to be send to window.

    Alt+F4 and X button causes WM_SYSCOMMAND message with SC_CLOSE type. You can decide if you wish to route this message further ( and cause WM_CLOSE in the end ).

    Here's a piece of code to catch this message. Return "True" from delegate if you wish to cancel default behaviour:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-19 02:54

    I'm not sure I like this at all but it's a question that you obviously have a reason for asking. if you were to take a stack trace in the OnClosing event you could look up for the Window.Close event.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题