GUI и визуальные компоненты

Диалоговое окно MessageBox в C# Windows Forms

Обновлено: · 6 мин чтения

MessageBox - готовое диалоговое окно Windows Forms для коротких сообщений, предупреждений и вопросов "да или нет". Здесь собраны все варианты вызова Show, наборы кнопок и значки, обработка ответа пользователя, примеры подтверждения закрытия формы, а также что делать в консоли, WPF и веб-проектах.

Диалоговое окно MessageBox в C# Windows Forms
Содержание
  1. Что такое MessageBox и как его вызвать
  2. Перегрузки метода Show
  3. Кнопки MessageBoxButtons
  4. Значки MessageBoxIcon
  5. Обработка ответа пользователя
  6. Подтверждение закрытия формы
  7. Показ ошибок и исключений
  8. Вывод значений и форматирование текста
  9. Владелец окна и расположение
  10. Консоль, WPF и другие платформы
  11. Типичные ошибки и советы
  12. Частые вопросы

Что такое MessageBox и как его вызвать

Класс MessageBox находится в пространстве имён System.Windows.Forms и содержит единственный практически нужный метод - статический Show. Он показывает модальное окно: пока пользователь не нажмёт кнопку, остальные окна приложения недоступны, а выполнение кода останавливается на вызове. Результат возвращается как значение перечисления DialogResult.

MessageBox.Show("Файл сохранён.");

В проекте Windows Forms подключать ничего дополнительно не нужно. В консольном приложении или проекте на .NET 8 без Windows Forms класса не будет: понадобится указать <UseWindowsForms>true</UseWindowsForms> в файле проекта и целевую платформу Windows, о чём подробнее в разделе про консоль.

Перегрузки метода Show

Метод имеет больше десятка перегрузок, но все они строятся из одних и тех же параметров. Основные сведены в таблицу.

ПараметрЧто задаёт
textТекст сообщения. Перевод строки добавляется через \n или Environment.NewLine
captionЗаголовок окна
buttonsНабор кнопок: MessageBoxButtons
iconЗначок: MessageBoxIcon
defaultButtonКнопка по умолчанию: MessageBoxDefaultButton
optionsДополнительные флаги, например выравнивание по правому краю
ownerОкно-владелец, над которым показывается диалог

Чаще всего используется вариант из четырёх аргументов: текст, заголовок, кнопки и значок.

MessageBox.Show(
    "Не удалось подключиться к серверу.",
    "Ошибка подключения",
    MessageBoxButtons.OK,
    MessageBoxIcon.Error);

Кнопки MessageBoxButtons

Перечисление определяет, какие кнопки увидит пользователь. Выбирайте набор под смысл вопроса: для информирования хватит OK, для подтверждения - YesNo, а для действия, которое можно отменить - YesNoCancel.

ЗначениеКнопки
OKOK
OKCancelOK, Отмена
YesNoДа, Нет
YesNoCancelДа, Нет, Отмена
RetryCancelПовторить, Отмена
AbortRetryIgnoreПрервать, Повторить, Пропустить
CancelTryContinueОтмена, Повторить, Продолжить

Надписи на кнопках подстраиваются под язык операционной системы, поэтому на русской Windows пользователь увидит "Да" и "Нет" без вашего участия. Изменить подписи стандартным способом нельзя: если нужны свои тексты, например "Сохранить" и "Не сохранять", создайте собственную форму.

Значки MessageBoxIcon

Значок подсказывает уровень важности и сопровождается системным звуком. Не злоупотребляйте им: ошибкой помечайте только настоящие сбои, а предупреждение используйте для действий с риском.

  • Information - обычное сообщение: "Операция завершена".
  • Warning - предупреждение: "Файл будет перезаписан".
  • Error (он же Stop и Hand) - ошибка выполнения.
  • Question - вопрос пользователю.
  • None - без значка.

Обработка ответа пользователя

Возвращаемое значение DialogResult показывает, какую кнопку нажали. Закрытие окна крестиком даёт тот же результат, что и кнопка Cancel, либо No, если Cancel в наборе нет, и это нужно учитывать.

DialogResult result = MessageBox.Show(
    "Удалить выбранный файл?",
    "Подтверждение",
    MessageBoxButtons.YesNo,
    MessageBoxIcon.Question,
    MessageBoxDefaultButton.Button2);

if (result == DialogResult.Yes)
{
    File.Delete(path);
}

Для опасных операций ставьте кнопкой по умолчанию безопасный вариант, как здесь через Button2: случайное нажатие Enter тогда не удалит файл. В вопросе с тремя вариантами удобно применять switch.

switch (MessageBox.Show("Сохранить изменения?", "Закрытие",
        MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning))
{
    case DialogResult.Yes:
        SaveDocument();
        break;
    case DialogResult.No:
        break;
    case DialogResult.Cancel:
        return;
}

Подтверждение закрытия формы

Один из самых частых сценариев - спросить пользователя перед выходом, если в окне остались несохранённые данные. Для этого подпишитесь на событие FormClosing и отмените закрытие через свойство Cancel.

private bool _isDirty;

private void MainForm_FormClosing(object? sender, FormClosingEventArgs e)
{
    if (!_isDirty) return;

    var answer = MessageBox.Show(
        "Есть несохранённые изменения. Сохранить их?",
        "Закрытие программы",
        MessageBoxButtons.YesNoCancel,
        MessageBoxIcon.Warning);

    if (answer == DialogResult.Cancel)
        e.Cancel = true;
    else if (answer == DialogResult.Yes)
        SaveDocument();
}

Не показывайте диалог, если закрытие инициировала сама система (выключение Windows): проверяйте e.CloseReason == CloseReason.UserClosing, иначе окно может заблокировать завершение работы системы.

Показ ошибок и исключений

Типичное применение - сообщить об исключении. Выводите понятный текст, а технические детали убирайте в журнал. Показывать пользователю ex.ToString() с трассировкой стека не стоит: он не поймёт, что делать, а часть сведений лучше не раскрывать.

try
{
    string text = File.ReadAllText(path);
    textBox1.Text = text;
}
catch (FileNotFoundException)
{
    MessageBox.Show($"Файл не найден:\n{path}", "Ошибка",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (UnauthorizedAccessException)
{
    MessageBox.Show("Нет доступа к файлу.", "Ошибка",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Если исключение связано с занятым файлом, посмотрите разбор в статье про проверку, открыт ли файл.

Вывод значений и форматирование текста

MessageBox принимает только строку, поэтому числа и даты нужно преобразовать. Интерполяция делает это компактно, а формат задаётся после двоеточия. Если нужно показать число в поле формы, а не в окне, пригодится статья про вывод числа в TextBox.

double price = 1234.5;
MessageBox.Show($"Итого: {price:N2} руб.\nДата: {DateTime.Now:dd.MM.yyyy HH:mm}",
    "Заказ", MessageBoxButtons.OK, MessageBoxIcon.Information);

// Показать элементы списка
MessageBox.Show(string.Join(Environment.NewLine, listBox1.Items.Cast<object>()));

Владелец окна и расположение

Если вызвать Show без владельца, окно появится по центру экрана и может оказаться позади формы. Передайте как первый аргумент текущую форму (this), и диалог встанет поверх неё, по центру владельца.

MessageBox.Show(this, "Готово", "Информация",
    MessageBoxButtons.OK, MessageBoxIcon.Information);

Положение окна и размеры сообщения изменить нельзя: ширина ограничена системой, а длинный текст переносится автоматически. Слишком большие сообщения лучше показывать в собственной форме с полем TextBox или RichTextBox и кнопкой "Копировать".

Консоль, WPF и другие платформы

Класс из Windows Forms работает в любом приложении Windows при подключённой сборке, но способ подключения зависит от проекта.

  • Консоль на .NET Framework: добавьте ссылку на сборку System.Windows.Forms и пишите using System.Windows.Forms;.
  • Консоль на .NET 8: в файле проекта укажите <TargetFramework>net8.0-windows</TargetFramework> и <UseWindowsForms>true</UseWindowsForms>.
  • WPF имеет собственный класс System.Windows.MessageBox с тем же методом Show, но с перечислениями MessageBoxButton и MessageBoxImage и результатом MessageBoxResult.
  • ASP.NET и Linux: MessageBox недоступен, сообщения показывают средствами веб-страницы или логами.
// WPF
var r = System.Windows.MessageBox.Show("Продолжить?", "Вопрос",
    System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question);
if (r == System.Windows.MessageBoxResult.Yes) { /* ... */ }

Для конфликтующих имён в одном файле (подключены и Forms, и WPF) указывайте полное имя класса, как в примере.

Типичные ошибки и советы

  • Вызов MessageBox из фонового потока работает, но окно может появиться позади основного. Лучше возвращаться в поток интерфейса, как описано в статье про обновление интерфейса из другого потока.
  • Сообщение внутри цикла: десятки подряд идущих окон выводят пользователя из себя. Накапливайте ошибки и показывайте одним окном.
  • Использование MessageBox для отладки: удобно, но блокирует поток. Для диагностики лучше Debug.WriteLine или журнал.
  • Сравнение результата со строками вместо DialogResult.
  • Слишком длинный текст и сообщения вроде "Ошибка!" без объяснения. Пишите, что случилось и что можно сделать.
  • Диалог, который появляется при каждом действии: пользователь привыкает нажимать "Да" не читая. Подтверждение имеет смысл только для необратимых действий.

Частые вопросы

Как вывести в MessageBox переменную?

Преобразуйте её в строку: MessageBox.Show(x.ToString()) или с интерполяцией MessageBox.Show($"Значение: {x}"). Прямая передача числа без преобразования не компилируется.

Как узнать, какую кнопку нажал пользователь?

Сохраните результат вызова в переменную типа DialogResult и сравните её со значениями Yes, No, OK или Cancel.

Как сделать перенос строки в сообщении?

Добавьте в текст \n либо Environment.NewLine. В интерполированной строке удобно писать $"Имя: {name}{Environment.NewLine}Возраст: {age}".

Можно ли поменять надписи на кнопках MessageBox?

Стандартными средствами нет, они зависят от языка системы. Создайте собственную форму с нужными кнопками и вызывайте её методом ShowDialog, получая тот же DialogResult.

Почему MessageBox не появляется в консольном приложении?

Скорее всего, не подключена сборка Windows Forms либо проект собран не под Windows. Включите UseWindowsForms и целевую платформу net8.0-windows.

Чем MessageBox отличается от собственного диалога?

MessageBox быстрый и привычный, но негибкий: нельзя менять размер, шрифт, надписи и добавлять поля ввода. Если нужен ввод текста или нестандартные кнопки, делайте отдельную форму.