2012-11-13 50 views
10

對window.close()的有一個聰明的方法來檢測一個窗口是否被如何區分「窗口關閉按鈕點擊(X)」在縮小處理

  • 關閉用戶按下(X )按鈕在窗口的右上角或
  • window.Close()已被編程調用。

我想在window.Closing處理程序中檢測到這一點。 我可以設置一個標誌,只要我打電話給window.Close(),但這不是一個非常漂亮的解決方案。

+0

雖然是可能的,這似乎不是一個好主意,區別對待..從一個UX點,請按住Alt-F4 /文件 - >退出/關閉按鈕關閉按鈕/關閉編程應該都是一樣的。 – stijn

+1

我認爲這是有道理的,當你使用關閉按鈕按下隱藏子窗口,但喜歡關閉應用程序關閉子窗口關閉按鈕。 – resp78

回答

12

我不確定我是否喜歡這個,但這是一個問題,你顯然有問題的理由。如果您要在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); 
} 
3

所不同的是以下內容:

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; 
    } 
} 
相關問題