Как отличить "Window close button click (X)" vs. window.Close() в закрывающем обработчике
Существует ли разумный способ определить, было ли закрыто окно с помощью
- Пользователь, нажимая кнопку (X) в правом верхнем углу окна или
- window.Close() вызывается программно.
Я хотел бы обнаружить это в окне. Обработчик закрытия.
Я могу установить флаг, когда я вызываю window.Close(), но это не очень красивое решение.
Ответы
Ответ 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 вызывает сообщение 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;
}
}