Замінити стандартну кнопку закриття (X) у формі Windows


75

Як я можу змінити те, що відбувається, коли користувач натискає кнопку закриття (червоний X) у програмі Windows Forms (у C #)?

Відповіді:


136

Ви можете замінити 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;
    }        
}

3
Я здогадуюсь, що він хоче мінімізувати до лотка, але ти отримуєш від мене +1 за те, що ти обережний.
Сем Гарвелл

4
@Jon B - слід перевірити близьку причину. Якщо Windows вимикається, ви не хочете показувати вікна повідомлень.
Філіп Уоллес

1
Я зробив це заявою перемикача, тому мені не потрібно прокручувати вправо, щоб прочитати праву сторону==
Сем Гарвелл

2
@Philip: ну, це залежить. Поле "Хочете зберегти" повинно відображатися щоразу, коли це актуально (є зміни), а скасування має скасувати вимкнення. Ось що трапляється з VS, наприклад. Набридливе "Хочеш закрити" повинно відображатися ... в ідеалі - ніколи, але якщо ти йдеш таким шляхом, той, який ти повинен обійти при вимкненні.
Р. Мартіньо Фернандес

@Phillip - чи насправді це рекомендується? Я вважаю, що більшість програм запитають вас, чи хочете ви зберегти зміни у зміненому файлі, незалежно від близької причини.
Groo

20

Перевизначте метод OnFormClosing .

ПОПЕРЕДЖЕННЯ. Вам потрібно перевірити CloseReason і змінити поведінку лише у випадку, якщо це UserClosing. Не слід вкладати сюди нічого, що могло б зупинити процедуру вимкнення Windows.

Зміни завершення роботи програми в Windows Vista

Це відповідає вимогам програми з логотипом Windows 7 .


Чи пропонують вони виняток, якщо ви просите користувача зберегти роботу перед вимкненням?
Крістофер Б. Адкінс

18

Однієї речі, якої бракує цих відповідей, і яку, мабуть, шукають новачки, є те, що хоча приємно влаштувати подію:

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

Це взагалі нічого не зробить, якщо ви не зареєструєте подію . Помістіть це в конструктор класу:

this.FormClosing += Form1_FormClosing;

10

Або перевизначте OnFormClosing, або зареєструйтесь для події FormClosing .

Це приклад перевизначення функції OnFormClosing у похідній формі:

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

Це приклад обробника події, щоб зупинити закриття форми, яка може бути в будь-якому класі:

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

Щоб отримати додаткові характеристики, перевірте властивість CloseReason на FormClosingEventArgs, щоб переконатися, що виконано відповідну дію. Можливо, ви захочете виконати альтернативну дію, лише якщо користувач намагається закрити форму.


8

як сказав Джон Б, але ви також хочете перевірити наявність ApplicationExitCallі TaskManagerClosingCloseReason:

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's OnFormClosing method:
    this.Hide();
}


3

Однією з ситуацій, коли цілком корисно мати можливість обробляти подію натискання кнопки 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);
    }

1

Це досить поширене запитання. Тут є одна хороша відповідь:

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


Якщо вам не зручно розміщувати свій код у події Form_Closing, єдиним іншим варіантом, який мені відомий, є "хак", який я використовував один-два рази. Не слід вдаватися до цього злому, але ось воно:


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

Потім ви можете додати стандартну кнопку і зробити його виглядати як кнопка закриття, і покласти очищенні коду там. В кінці події кнопки просто зателефонуйте this.Close()(C #) або Me.Close()(VB)


Чому б людині не почуватись комфортно під час закриття події? IMHO додає власну (але переконливу) кнопку Закрити не настільки тривіально (особливо, якщо взяти до уваги ефекти переходу та речі Aero, які ви зазвичай отримуєте без болю).
Groo

У відповіді, на яку я посилався, особа, яка поставила запитання, з якихось причин не хотіла використовувати подію Form_Closing. Я не впевнений, у чому його причина, але він не хотів цим користуватися. Коли я використовував хак, я просто хотів закрити кнопку з іншим виглядом.
Девід

Іншими словами, інша відповідь була як пов’язана з (досить справедливою), так і скопійована, саме тому половина відповіді є неактуальною, а решта рекомендує те, що тут не має жодного обґрунтування.
jwg

0

Прийнята відповідь працює досить добре. Альтернативний метод, який я використав, - це створення методу 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) мінімізує Додаток.


-1
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);
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.