Переопределить стандартную кнопку закрытия (X) в форме Windows

Как мне изменить, что происходит, когда пользователь нажимает кнопку закрытия (красный X) в приложении Windows Forms (на С#)?

Ответ 1

Вы можете переопределить OnFormClosing, чтобы сделать это. Просто будьте осторожны, вы не делаете ничего слишком неожиданного, так как щелчок "X" для закрытия - это хорошо понятое поведение.

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);

    if (e.CloseReason == CloseReason.WindowsShutDown) return;

    // Confirm user wants to close
    switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing", MessageBoxButtons.YesNo))
    {
    case DialogResult.No:
        e.Cancel = true;
        break;
    default:
        break;
    }        
}

Ответ 2

Отмените метод OnFormClosing.

ВНИМАНИЕ: Вам нужно проверить CloseReason и изменить поведение только в том случае, если это UserClosing. Вы не должны помещать что-либо здесь, что остановило бы процедуру отключения Windows.

Отключение приложений в Windows Vista

Это из Требования к программе логотипа Windows 7.

Ответ 3

Одна вещь, которой эти ответы не хватает, и какие новички, вероятно, ищут, заключается в том, что, хотя приятно иметь событие:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // do something
}

Он ничего не собирается делать, если вы не зарегистрируете событие. Поместите это в конструктор класса:

this.FormClosing += Form1_FormClosing;

Ответ 4

Либо переопределите OnFormClosing, либо зарегистрируйтесь для события FormClosing.

Это пример переопределения функции OnFormClosing в производной форме:

protected override void OnFormClosing(FormClosingEventArgs e)
{
   e.Cancel = true;
}

Это пример обработчика события, чтобы остановить закрытие формы, которая может быть в любом классе:

private void FormClosing(object sender,FormClosingEventArgs e)
{  
   e.Cancel = true;
}

Чтобы получить дополнительные возможности, проверьте свойство CloseReason на FormClosingEventArgs, чтобы убедиться, что выполнено соответствующее действие. Вы можете выполнить только альтернативное действие, если пользователь пытается закрыть форму.

Ответ 5

как сказал Джон Б, но вы также захотите проверить ApplicationExitCall и TaskManagerClosing CloseReason:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (  e.CloseReason == CloseReason.WindowsShutDown 
        ||e.CloseReason == CloseReason.ApplicationExitCall
        ||e.CloseReason == CloseReason.TaskManagerClosing) { 
       return; 
    }
    e.Cancel = true;
    //assuming you want the close-button to only hide the form, 
    //and are overriding the form OnFormClosing method:
    this.Hide();
}

Ответ 7

Одна из ситуаций, когда весьма полезно иметь возможность обрабатывать событие нажатия кнопки x, - это когда вы используете форму, являющуюся контейнером MDI. Причина в том, что закрытие и закрытие событий воспитываются сначала с детьми и, наконец, с родителем. Таким образом, в одном сценарии пользователь нажимает кнопку x для закрытия приложения, а родитель MDI запрашивает подтверждение. В случае, если он решает не закрывать приложение, но продолжать то, что он делает, дети уже обработали событие закрытия, которое потенциально потеряло информацию/работа. Одним из решений является перехват сообщения WM_CLOSE из цикла сообщений Windows в основной форме приложения (т.е. Закрытой, завершает приложение) следующим образом:

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0010) // WM_CLOSE
        {
            // If we don't want to close this window 
            if (ShowConfirmation("Are you sure?") != DialogResult.Yes) return;
        }

        base.WndProc(ref m);
    }

Ответ 8

Это довольно часто задаваемый вопрос. Один хороший ответ здесь:

VB.NET перегружает функции по умолчанию, когда пользователь нажимает кнопку X (Закрыть программу)


Если вы не чувствуете себя комфортно, добавляя свой код в событие Form_Closing, единственная другая опция, о которой я знаю, - это "взлом", который я использовал один или два раза. Не нужно прибегать к этому взлому, но вот оно:


Не используйте обычную кнопку закрытия. Вместо этого создайте свою форму, чтобы она не имела ControlBox. Вы можете сделать это, установив ControlBox = false в форме, и в этом случае вы все равно будете иметь нормальный бар в верхней части формы или вы можете установить форму FormBorderStyle в "None". Если вы идете по этому второму маршруту, не будет ни одного бара в верхней части или любой другой видимой границы, поэтому вам придется имитировать их либо путем рисования формы, либо путем художественного использования элементов управления Panel.

Затем вы можете добавить стандартную кнопку и сделать ее выглядеть как кнопка закрытия и поместить туда код очистки. В конце события кнопки просто вызовите this.Close() (С#) или Me.Close() (VB)

Ответ 9

protected override bool ProcessCmdKey(ref Message msg, Keys dataKey)
    {
        if (dataKey == Keys.Escape)
        {
            this.Close();
            //this.Visible = false;
            //Plus clear values from form, if Visible false.
        }
        return base.ProcessCmdKey(ref msg, dataKey);
    }

Ответ 10

Принятый ответ работает достаточно хорошо. Альтернативным методом, который я использовал, является создание метода FormClosing для основной формы. Это очень похоже на переопределение. Мой пример - это приложение, которое сворачивается в системный лоток при нажатии кнопки закрытия формы.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.ApplicationExitCall)
        {
            return;
        }
        else
        {
            e.Cancel = true;
            WindowState = FormWindowState.Minimized;
        }            
    }

Это позволит ALT + F4 или что-либо в приложении, вызывающем Application.Exit();, чтобы действовать как нормальное нажатие (X) минимизирует приложение.

Ответ 11

  • Просто зайдите в "Program.Designer.cs"
  • Найдите функцию с именем protected override void Dispose(bool disposing)
  • Комментировать или удалить строку base.Dispose(disposing);
  • Вместо этой строки Напишите код для вашей закрытой операции