Додаток, який використовує кілька вікон, називається багатовіконним.
З точки зору програмування, кожне вікно є формою. Тобто, багатовіконний інтерфейс - це інтерфейс з кількох пов'язаних форм.
Для Windows-додатка за замовчуванням створюється клас Form1, який є похідним від класу Form. Якщо в проект додається нова форма, використовуючи пункт меню Проект, Додати форму, то створюється об'єкт класу Form2, Form3,... Усі ці класи також є похідними від класу Form.
Щоб додати ще одну форму до проекту, потрібно виконати наступну команду:

Отримуємо:
Вказуємо ім'я форми або залишаємо запропоноване та натискаємо "Додати".
Форму можна:
Якщо ми хочемо, щоб у кожний поточний момент була відкрита тільки одна форма, потрібно вжити певні заходи, щоб при закритті (приховуванні) форми відкривалась інша форма.
В іншому випадку можлива неприємна ситуація, коли всі форми закриті, і нічого не можна зробити, але додаток не завершений.
Звичайно, завжди є вихід - завжди можна натиснути комбінацію клавіш CTRL + ALT + DEL і завершити будь-який додаток за допомогою Диспетчера завдань.
Кожне додаток містить одне головне вікно - клас Form1. Клас головного вікна додатку містить точку входу в додаток (статичний метод Main у класі Program).
При закритті головного вікна, закриваються всі інші вікна, і додаток завершує роботу. Зазвичай головна форма проекту завжди відкрита, тоді як інші форми проекту відкриваються і закриваються (приховуються). Завершити додаток програмно можна за допомогою статичного методу Exit класу Application.
Головне вікно створюється автоматично при створенні додатка.
Діалогові вікна використовуються для введення деякої інформації.
Зазвичай таке вікно оформлюється як модальне. Модальне вікно не дозволяє користувачеві перемикатися на інші вікна того ж додатку, поки воно не буде закрите.
Для відображення форми як модального вікна використовується метод ShowDialog, а також встановлюються наступні властивості:
Інформаційні вікна - це немодальні вікна.
Вони використовуються в тих випадках, коли користувач сам обирає - залишити на екрані певну інформацію чи ні.
Для відкриття такої форми використовується метод Show.
При створенні багатовіконних додатків доводиться передавати деякі дані з одного вікна в інше. Розглянемо два способи передачі даних:
Створимо додаток з чотирма вікнами. Для передачі даних з одного вікна в інше, скористаємося допоміжним статичним класом.




Елементи форми:

Обробники події Click для кожної кнопки:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Налаштування властивостей форми
this.Text = "Головне меню";
this.Size = new Size(400, 300);
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = Color.LightGray;
// Налаштування кнопок
button1.Text = "Калькулятор параметрів";
button2.Text = "Перегляд результатів";
button3.Text = "Інформація про розробника";
// Додаткові налаштування стилів
foreach (Button btn in this.Controls.OfType<Button>())
{
btn.Font = new Font("Arial", 10, FontStyle.Bold);
btn.Size = new Size(250, 50);
btn.BackColor = Color.LightBlue;
btn.ForeColor = Color.DarkBlue;
}
// Центрування кнопок
CenterButtons();
}
private void CenterButtons()
{
int startY = 50;
int spacing = 20;
button1.Location = new Point(
(this.ClientSize.Width - button1.Width) / 2,
startY);
button2.Location = new Point(
(this.ClientSize.Width - button2.Width) / 2,
button1.Bottom + spacing);
button3.Location = new Point(
(this.ClientSize.Width - button3.Width) / 2,
button2.Bottom + spacing);
}
private void button1_Click(object sender, EventArgs e)
{
// Відкриття форми калькулятора у модальному режимі
using (Form2 calculatorForm = new Form2())
{
calculatorForm.ShowDialog();
}
}
private void button2_Click(object sender, EventArgs e)
{
// Відкриття форми результатів
Form3 resultsForm = new Form3();
resultsForm.Show();
}
private void button3_Click(object sender, EventArgs e)
{
// Відкриття форми з інформацією про розробника
Form4 aboutForm = new Form4();
aboutForm.Show();
}
}
У кожному обробнику створюється відповідна форма і вона показується за допомогою методу Show або ShowDialog.
Створимо статичний клас Class1, який буде містити три поля:
А також властивості для доступу до цих полів:
///
/// Статичний клас для зберігання результатів обчислень параметрів кола
///
public static class Class1
{
private static double area; // Площа круга
private static double circumference; // Довжина кола
private static int backgroundColor; // Вибір кольору фону (0 - червоний, 1 - бірюзовий)
///
/// Властивість для доступу до площі круга
///
public static double S
{
get { return area; }
set
{
if (value >= 0)
area = value;
else
throw new ArgumentOutOfRangeException("Площа не може бути від'ємною");
}
}
///
/// Властивість для доступу до довжини кола
///
public static double L
{
get { return circumference; }
set
{
if (value >= 0)
circumference = value;
else
throw new ArgumentOutOfRangeException("Довжина не може бути від'ємною");
}
}
///
/// Властивість для доступу до вибору кольору фону
///
public static int N
{
get { return backgroundColor; }
set
{
if (value == 0 || value == 1)
backgroundColor = value;
else
throw new ArgumentOutOfRangeException("Допустимі значення: 0 або 1");
}
}
///
/// Скидання всіх значень до початкового стану
///
public static void Reset()
{
area = 0;
circumference = 0;
backgroundColor = 0;
}
}
Елементи форми:

Оскільки це вікно буде модальним, то встановимо такі властивості форми:
Обробник події Click для кнопки button1 присвоює значення полям s, l, n статичного класу.
Обробник події Click для кнопки button2 очищує поля форми Form2.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
// Налаштування форми
this.Text = "Обчислення параметрів кола";
this.StartPosition = FormStartPosition.CenterScreen;
this.Size = new Size(350, 250);
// Налаштування елементів керування
button1.Text = "Обчислити";
button2.Text = "Очистити";
label1.Text = "Введіть радіус:";
checkBox1.Text = "Обчислити площу";
checkBox2.Text = "Обчислити довжину";
radioButton1.Text = "Червоний фон";
radioButton2.Text = "Бірюзовий фон";
}
private void button1_Click(object sender, EventArgs e)
{
try
{
// Отримання радіусу з текстового поля
double radius = Convert.ToDouble(textBox1.Text);
// Перевірка на додатнє значення радіусу
if (radius <= 0)
{
MessageBox.Show("Радіус повинен бути більше нуля!", "Помилка",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// Скидання попередніх результатів
Class1.S = 0;
Class1.L = 0;
Class1.N = 0;
// Обчислення площі, якщо обрано
if (checkBox1.Checked)
{
Class1.S = Math.PI * Math.Pow(radius, 2);
}
// Обчислення довжини кола, якщо обрано
if (checkBox2.Checked)
{
Class1.L = 2 * Math.PI * radius;
}
// Вибір кольору фону
Class1.N = radioButton1.Checked ? 0 : 1;
MessageBox.Show("Обчислення виконано успішно!", "Результат",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (FormatException)
{
MessageBox.Show("Будь ласка, введіть коректне числове значення радіусу!",
"Помилка вводу",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show($"Сталася помилка: {ex.Message}",
"Помилка",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void button2_Click(object sender, EventArgs e)
{
// Очищення форми
textBox1.Text = "";
checkBox1.Checked = false;
checkBox2.Checked = false;
radioButton1.Checked = true; // Встановлення значення за замовчуванням
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// Дозволяємо тільки цифри, крапку та керуючі символи
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
{
e.Handled = true;
}
// Перевірка на наявність лише однієї крапки
if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1)
{
e.Handled = true;
}
}
}
У конструкторі на формі Form3 розмістимо 4 порожні елементи label. В них помістимо результати обчислень.


В обробнику події Load для Form3 зчитуємо значення полів s, l, n статичного класу і виводимо в порожні елементи Label.
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
// Налаштування форми
this.Text = "Результати обчислень";
this.StartPosition = FormStartPosition.CenterScreen;
this.Size = new Size(350, 200);
}
private void Form3_Load(object sender, EventArgs e)
{
// Встановлення кольору фону форми
this.BackColor = (Class1.N == 0) ? Color.Red : Color.DarkCyan;
// Налаштування шрифту для всіх міток
Font labelFont = new Font("Arial", 10, FontStyle.Bold);
// Відображення площі круга, якщо вона обчислена
if (Class1.S != 0)
{
label1.Text = "Площа круга:";
label1.Font = labelFont;
label1.ForeColor = Color.White;
label2.Text = Class1.S.ToString("F3") + " кв.од.";
label2.Font = labelFont;
label2.ForeColor = Color.White;
}
// Відображення довжини кола, якщо вона обчислена
if (Class1.L != 0)
{
label3.Text = "Довжина кола:";
label3.Font = labelFont;
label3.ForeColor = Color.White;
label4.Text = Class1.L.ToString("F3") + " од.";
label4.Font = labelFont;
label4.ForeColor = Color.White;
}
// Центрування міток на формі
CenterLabels();
}
private void CenterLabels()
{
// Центрування пар міток (текст + значення)
int startY = 30;
int spacing = 30;
if (Class1.S != 0)
{
label1.Location = new Point(50, startY);
label2.Location = new Point(180, startY);
startY += spacing;
}
if (Class1.L != 0)
{
label3.Location = new Point(50, startY);
label4.Location = new Point(180, startY);
}
}
}
У класі Form4 в елемент label поміщаємо прізвище та ім'я розробника:
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
// Додаткові налаштування форми при ініціалізації
this.Text = "Інформація про розробника";
this.StartPosition = FormStartPosition.CenterScreen;
this.Size = new Size(400, 200);
}
private void Form4_Load(object sender, EventArgs e)
{
// Налаштування мітки з інформацією про розробника
label1.Text = "Розробник: Коваленко Петро";
label1.Font = new Font("Arial", 12, FontStyle.Bold);
label1.ForeColor = Color.DarkBlue;
label1.AutoSize = true;
label1.Location = new Point(
(this.ClientSize.Width - label1.Width) / 2,
(this.ClientSize.Height - label1.Height) / 2
);
// Додаткові елементи інтерфейсу
var versionLabel = new Label();
versionLabel.Text = "Версія: 1.0";
versionLabel.Font = new Font("Arial", 10);
versionLabel.AutoSize = true;
versionLabel.Location = new Point(
(this.ClientSize.Width - versionLabel.Width) / 2,
label1.Bottom + 20
);
this.Controls.Add(versionLabel);
}
}
