Is there a clever way to detect whether a window was closed by
I would like to detect this in the window.Closing handler. I could set a flag whenever I call window.Close(), but this is not a very pretty solution.
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);
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With