Як вимкнути форму закриття Alt + F4?


79

Який найкращий спосіб вимкнути Alt+F4 у формі ac # win, щоб не дати користувачеві закрити форму?

Я використовую форму як спливаюче діалогове вікно для відображення індикатора виконання, і я не хочу, щоб користувач міг його закрити.


Чи не можете ви допитати буфер клавіатури в обробнику подій FormClosing (чи є у вас доступ до цього?), Щоб se, якщо натиснуто [Alt] + [F4], скасувати, якщо true, продовжити, якщо ні?
ТЗ.

Відповіді:


107

Це робить роботу:

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

Редагувати: у відповідь на занепокоєння pix0rs - так, ви праві, що не зможете програмно закрити програму. Однак ви можете просто видалити обробник події для події form_closing перед закриттям форми:

this.FormClosing -= new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
this.Close();

4
Я підозрюю, що більшість людей застосовують цей метод у відповідній формі (Form1). У цьому випадку рекомендується не приєднувати делегата, а замінювати метод OnFormClosing. "Метод OnFormClosing також дозволяє похідним класам обробляти подію без приєднання делегата. Це найкращий прийом для обробки події у похідному класі." tinyurl.com/3dzzljq
antsyawn

10
Я зробив би обробник події , як , наприклад: e.Cancel = (e.Reason == CloseReason.UserClosing);. Таким чином ви гарантуєте, що не закриєте лише тоді, коли КОРИСТУВАЧ намагається закрити форму.
Паулу Сантос

Цей підхід має одну велику проблему: якщо ви хочете вимкнути / перезапустити свій ПК, він також скасує цей запит (принаймні в Windows XP)
conceptacid,

Це БІЛІАНТНО! Я особливо люблю видаляти подію, коли ви хочете закрити форму. Це так ПРОСТО !!!
Буде

@Will: Я відредагував відповідь. Зараз є рішення, яке працює без видалення обробника подій.
Thomas Weller 02

59

Якщо ви подивіться на значення з FormClosingEventArgs e.CloseReason, він розповість вам , чому форма закривається. Потім ви можете вирішити, що робити, можливі значення:

Ім'я учасника - Опис


Жоден - Причина закриття не була визначена або не може бути визначена.

WindowsShutDown - Операційна система закриває всі програми перед вимкненням.

MdiFormClosing - батьківська форма цієї форми багаторазового інтерфейсу документа (MDI) закривається.

UserClosing - Користувач закриває форму через користувальницький інтерфейс (UI), наприклад, натискаючи кнопку Закрити у вікні форми, вибираючи Закрити в меню керування вікном або натискаючи ALT+ F4.

TaskManagerClosing - Диспетчер завдань Microsoft Windows закриває програму.

FormOwnerClosing - форма власника закривається.

ApplicationExitCall - викликано метод Exit класу Application.


8
Якби тільки вони вибухнули UserClosing, щоб бути більш детальним, щоб ви могли спеціально націлити Alt + F4 ...
blak3r

if (e.CloseReason == CloseReason.UserClosing) {e.Cancel = true; }
adnan2

Поєднуйте CloseReasonі DialogResultдля досягнення найкращих результатів.
Thomas Weller

25

Я вважаю, що це правильний спосіб зробити це:

protected override void OnFormClosing(FormClosingEventArgs e)
{
  switch (e.CloseReason)
  {
    case CloseReason.UserClosing:
      e.Cancel = true;
      break;
  }

  base.OnFormClosing(e);
}

краще замінити перерву на повернення
Бахадир Яган

Насправді я вважаю, що правильний шаблон - встановити прапорець скасування на true, а потім викликати базовий клас. При перевизначенні методів On [Event] важливо викликати базовий клас, щоб будь-які передплатники подій також отримували повідомлення про подію. Так, у цьому випадку легко подумати, що оскільки ви скасували подію, то ніхто інший не повинен про це знати, але я не вважаю правильним робити це припущення.
antsyawn

Я не впевнений у причині, але якщо я зателефоную до базового класу, моя програма вийде з ладу після чергового наступного натискання Alt + F4. Спочатку я думав, що це тому, що звичайний F4 має якесь інше значення в моєму додатку, але довгий сеанс налагодження показав інше. У будь-якому випадку, це все одно може бути конкретний випадок з мого боку. Дякую за цю чудову відповідь.
Бахадир Яган

Виклик базового класу також спричиняє збій мого додатка на наступних Alt + F4. Я підозрюю, що базовий клас не перевіряє e.Cancel і все одно намагається знищити форму.
Натан Єллін,

Потрібно вивчити, чому у вашої програми виникає збій - цілком ймовірно, ви десь щось робите неправильно. У документації сказано: "Подія FormClosing відбувається, коли форма закривається. Коли форма закрита, вона утилізується, звільняючи всі ресурси, пов’язані з формою. Якщо скасувати цю подію, форма залишається відкритою. Щоб скасувати закриття форми, встановіть для властивості Cancel для FormClosingEventArgs, що передається у ваш обробник подій, значення true. " tinyurl.com/3tb7y9q
antsyawn

16

Зверніть увагу, що програма вважається поганою формою, щоб повністю запобігти закриттю. Вам слід перевірити аргументи події для події Closing, щоб визначити, як і чому вашу програму було запропоновано закрити. Якщо це пов’язано з вимкненням Windows, не слід перешкоджати закриттю.


13

Ви можете обробити FormClosingподію та встановити FormClosingEventArgs.Cancelна true.


12

Я використовую форму як спливаюче діалогове вікно для відображення індикатора виконання, і я не хочу, щоб користувач міг його закрити.

Якщо користувач твердо вирішив закрити ваш додаток (і обізнаний) настільки, щоб натиснути alt + f4, він, швидше за все, також буде достатньо обізнаним, щоб запустити диспетчер завдань і замість цього вбити вашу програму.

Принаймні за допомогою alt + f4 ваш додаток може витончено вимкнути роботу, а не просто змусити людей її вбити. З досвіду, люди, які вбивають ваш додаток, означають пошкоджені файли конфігурації, пошкоджені бази даних, напівфабрикати, які ви не можете відновити, та багато інших болючих справ.

Принаймні, підкажіть їм "ви впевнені", а не відверто запобігайте цьому.


8

Це хак для відключення Alt+ F4.

private void test_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.ModifierKeys == Keys.Alt || this.ModifierKeys == Keys.F4) 
    { 
        e.Cancel = true; 
    }    
}

Я можу підтвердити, що це працює. Однак, якщо використовується System.Windows.Forms, вам потрібно буде перевірити статичну Control.ModifierKeysвластивість, а не this.ModifierKeysвластивість (як показано у фрагменті вище).
Спеціальний соус

Цей підхід кращий, оскільки таким чином ви можете дозволити закрити свою програму методом Close (), який поділяє причину CloseReason.UserClosing. Мене турбує такий підхід у тому, що інформація про натиснуту клавішу завжди є точною?
Адам Л.С.

4

Підписатися на подію FormClosing

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = e.CloseReason == CloseReason.UserClosing;
}

Тільки один рядок у тілі методу.


3

Це робить роботу:

bool myButtonWasClicked = false;
private void Exit_Click(object sender, EventArgs e)
{
  myButtonWasClicked = true;
  Application.Exit();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
  if (myButtonWasClicked)
  {
    e.Cancel = false;
  }
  else
  {
    e.Cancel = true;
  }


}

2

Чи буде викликано FormClosing навіть тоді, коли ви програмно закриваєте вікно? Якщо так, ви, мабуть, захочете додати якийсь код, щоб дозволити форму закрити, коли закінчите з нею (замість того, щоб завжди скасовувати операцію)


Відповідь на ваше запитання - "так". Будь ласка, не публікуйте додаткові запитання як відповідь. Уже є дійсно хороша, високо оцінена та прийнята відповідь. Якщо ви не проти, чи не могли б ви видалити свою? Це насправді не додає вартості. Я підтримав 3 ваші відповіді, щоб компенсувати видалення.
Thomas Weller,

-3

Приховати кнопку закриття на формі, використовуючи наступне в конструкторі форми:

this.ControlBox = false;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.