You are on page 1of 25

Лекція 7.

Візуальне середовище Visual C# для роботи з Windows


Forms додатками

Початок роботи над Windows Forms додатком в Visual C#.

Створення додатка. Для створення проекту вибираємо в


меню File | New | Project і у вікні вибираємо Windows Forms Application в розділі
мови програмування Visual C # | Windows (рис. 1) Назвемо його новий
додаток OurFirstVisualApplication.

Давайте подивимося, які модулі додані в рішення. Їх всього два


- Forml.cs (цей модуль складається з декількох файлів) і Program.cs. Почнемо з
другого файлу, тому що саме з нього починається виконання програми і там
знаходиться метод Main (). Код файлу ви можете побачити в лістингу 1.

Лістинг 1. Вміст файлу Program.cs

using System;

using System.Collections.Generic; using


System.Windows.Forms;

namespace OurFirstVisualApplication {
static class Program {
[STAThread] static void Main()
{
Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Forml());


}
}
}
Рисунок 1. Вікно створення нового проекту (виділено пункт для створення
візуального додатка)

Файл Program.сs потрібен для запуску проєкту, в якому оголошено клас з


методом Main(). Він не несе в собі ніякої логіки, крім створення програми та
відображення головного вікна програми. Частіше за все в цей файл ви заглядати
не будете, але знати про його існування бажано.

1.1. Простір імен


Файл Program.cs підключає три простори імен, з якими буде відбуватися
робота. Насправді для компіляції програми досить тільки двох просторів -
першого і третього. Друге місце не потрібно і в даному коді не використовується,
тому ми не будемо його поки розглядати. Даний простір імен відноситься до
колекцій.

З необхідних залишаються два простори імен:

System - ми підключали цей простір імен для всіх додатків, які писали до
сих пір, а точніше, майстер підключав його замість нас. У цьому просторі в .NET
оголошені основні типи даних і все, без чого не виживе ні один додаток .NET,
який хоч щось робить;
System.windows.Forms - в цьому просторі імен розміщено все, що
необхідно для функціонування форми. Формами в .NET називають проект
майбутнього вікна. Якщо клас - це специфікація, по якій створюється об'єкт, то
форма-це специфікація, по якій створюється вікно. Ми плануємо працювати з
візуальним інтерфейсом, тому даний простір імен просто необхідний.

Як дізнатися, які простори імен підключати, а які не потрібно? Тут може


допомогти файл допомоги і MSDN, де при описі кожного класу, методу або
властивості обов'язково вказується, в якому просторі імен його можна знайти.
Відкрийте файл допомоги (команда меню Help | Index (Допомога | Індекс)) і
введіть в рядок пошуку Look for (Шукати) зліва: Application class. Клацніть двічі
по знайденому імені, і відкриється сторінка допомоги за даним класу (рис. 2).

На рис. 2 я виділив той фрагмент, де якраз і написано, в якому просторі


імен знаходяться опис та збірки (dll-файл) з реалізацією класу. Нас більше
цікавить саме простір імен, а не збірка. Мені жодного разу не доводилося
використовувати файл збірки, принаймні цей. Файл зборки може стати в нагоді,
якщо ви використовуєте щось специфічне. Всі основні файли додаються в розділ
References проекту автоматично при створенні проекту. Якщо ви будете
використовувати щось специфічне, то спочатку слід під'єднати потрібний файл
збірки самостійно.

Другий метод дізнатися простір імен - не думати про нього, а покласти


всю головний біль на середовище розробки. У Visual Studio голова досить
хороша, і вона з легкістю вирішить таку задачу.

Спробуйте зараз ввести десь У коді методу Main () слово OleDbConnection.


Це клас, який використовується для з'єднання з базами даних, і компілятор не
знайде його серед підключених просторів імен і звичайно ж підкреслить. Тепер
ви можете натиснути правою кнопкою по підкресленому імені, в контекстному
меню розкрити пункт Resolve (Отримати), і в його підменю будуть перераховані
простори імен, в яких середовище розробки змогла знайти вказане слово (рис. 3).
Рисунок 2. Файл допомоги по класу Application

У контекстному меню доступні два варіанти вирішення проблеми, між


якими буде знаходитися роздільник. Вище роздільника будуть варіанти, які
додають в початок модуля коду using з обраним простором імен. Варіанти нижче
роздільника змінюють коротку назву методу на повне. Тобто у випадку з типом
даних oleDbConnection, якщо ви виберете варіант нижче роздільника, то тип
даних заміниться на System.Data.OleDb.OleDbConnection. Якщо ВИ знаєте, що це
єдине звернення до цього типу даних, то можна використовувати повний шлях,
але якщо в модулі коду ви будете використовувати цей тип даних багато разів, то
простіше буде відразу додати його в розділ using.

Частіше за все в цьому підменю буде тільки один варіант як до


роздільника, так і після, але деякі імена можуть бути оголошені як для Windows,
так і для Web. У таких випадках потрібно вибрати потрібну збірку. Це не складно,
тому що для Інтернету найчастіше використовується простір імен System.web.
Наприклад, клас Application для інтернет-програмування знаходиться в Microsoft
.Web. Administration. Ось воно ключове слово "Web", яке знаходиться в середині.
Рисунок 3. Контекстне меню дозволяє вирішити проблему підключення
просторів імен

Простір імен за замовчуванням для вашого проекту можна змінити. Для


цього клацніть правою кнопкою миші по імені проекту і виберіть в контекстному
меню пункт Properties, щоб змінити властивості проекту. Тут в розділі Application
в поле Default namespace (Простір імен за замовчуванням) ви можете змінити ім'я
простору імен. При цьому вже існуючий код залишиться в старому просторі імен.
Існуючий код змінюватися автоматично не буде, а ось нові файли, які будуть
додаватися до проекту, будуть потрапляти вже в новий простір. Якщо вам
потрібно перенести існуючий код в новий простір, то потрібно буде зробити це
руками, змінюючи поточний простір імен на новий. Можна залишити і старе ім'я,
тому що в одній збірці можуть бути і два, і три різних простори імен, якщо вас це
влаштовує.

1.2. Потоки
Зверніть увагу, що перед методом Main () в квадратних дужках стоїть
ключове слово STAThread. Воно вказує на те, що модель потоків для додатка буде
поодинока. Такий атрибут повинен бути вказаний для всіх точок входу в
WinForms-додатка. Якщо він буде відсутній, то компоненти Windows можуть
працювати некоректно.

Без атрибуту STAThread додаток буде використовувати многопоточную


модель поділу, яка не підтримуються для Windows Forms. Множинність потоків
підтримується, але STAThread - це модель поділу коду (multi-threaded apartment
model).

1.3. Клас Application

У лістингу 1 в методі Main() усі рядки коду є зверненням до класу


Application, який надає статичні властивості і методи (це означає, що не потрібно
створювати екземпляр класу, щоб їх викликати) для підтримки роботи додатку.
Основними методами є запуск і зупинка додатка, а також обробка повідомлень
Windows. При виникненні будь-яких ситуацій ОС відправляє вікну подію, і вікно
повинно опрацювати цю подію. Наприклад, якщо користувач натиснув на кнопку
закриття вікна, то цьому вікну направляється подія WM_CLOSE. Зловивши цю
подію, вікно повинно відреагувати, звільнити ресурси і приготуватися до
знищення. Будь-яка повкдінка користувача, включаючи натискання клавіш на
клавіатурі і рух курсору миші, обробляє ОС, а потім за допомогою повідомлень
відправляє зміни в додаток.

Щоб відловлювати повідомлення, які надсилає додатку операційна


система, в додатку повинен бути запущений цикл. У таких мовах, як C/C--, цикл
отримує від ОС повідомлення, обробляє його і чекає наступного повідомлення.
Цей цикл триває доти, поки не відбудеться вихід з додатку.

Клас Application бере на себе всю відповідальність за отримання


повідомлень від системи і перенаправлення їх у вікна, щоб ви могли обробити їх.
Трохи пізніше ми навчимося ловити повідомлення, а поки нам потрібно знати,
що за підготовку повідомлення для обробки відповідає саме клас Application.

Розглянемо методи, які викликаються в класі, який згенерував нам


майстер Visual Studio. Перший метод класу Application, який ми викликаємо -
EnabieVisualStyles (). Цей метод включає відображення в стилях ОС, на якій
запущено програму. Якщо видалити цей рядок і запустити програму, то всі
елементи управління будуть виглядати в стилі Windows 9х з квадратними кутами
навіть в Windows Vista. Не бачу сенсу повертатися в доісторичні часи візуального
інтерфейсу, але якщо вам раптом це знадобиться, тепер ви знаєте, який рядок
потрібно видалити.

Наступний метод додатка, який викликає програма


- SetCompatibleTextRenderingDefault () Деякі елементи управління можуть
відображати текст за допомогою старих функцій GDI або за допомогою нових
функцій GDI -. Якщо методом SetCompatibleTextRenderingDefault () передати
Значення false, то будуть використовуватися функції GDI -.
Це все були підготовчі методи, а останній метод Run () є найбільш
важливим. Цей метод запускає прихований цикл обробки повідомлень ОС і
робить видимою форму, яка передається в якості параметра. Як параметр в
нашому прикладі передається ініціалізація об'єкта класу Form1, і для цього
викликається конструктор класу за допомогою оператора new. Просто ми завжди
присвоювали результат виконання new змінній, а в цьому випадку нам змінна не
потрібна, і ми більше не будемо використовувати об'єкт в методі Main (), тому,
ніде нічого не зберігаючи, відразу передаємо новий об'єкт методу. Те ж саме
можна було написати так:

Form1 form - new Forml();


Application.Run(form);

2. Нащадок Form для головної форми


Тепер подивимося на вміст файлу Form.css. Якщо розкрити гілку форми,
то ви побачите, що там є ще два файли: Forml.Designer.сs і Form.resx. Виходить,
що форма описана аж в трьох файлах? Так і є. Звичайно ж, все можна було
реалізувати в одному файлі з кодом, але розбиття зроблено для вашої ж зручності.

2.1. Ресурси програми


У resx-файлі зберігаються атрибути файлу коду, і з ним працює
середовище розробки. Мені поки що жодного разу не доводилося редагувати
його безпосередньо, в основному я робив це з середовища розробки. Пам'ятайте,
що там середовище розробки зберігає параметри форми для внутрішнього
використання і ресурси програми.

Але є глобальний файл ресурсів, з яким ви можете працювати без


проблем. Він знаходиться в папці Properties проекту і називається Resources.resx.
У ньому розташовані ресурси програми, і вони можуть бути доступні будь-якій
формі проекту.

Ви можете створювати в файлі resx ресурси, такі як рядки, зображення і т.


д., Які в подальшому можна буде використовувати в програмі.

Спробуйте клацнути двічі по файлу Forml.resx в


панелі Solution Explorer. Перед вами відкриється редактор ресурсів форми (рис.
4).
Рисунок 4. Окно редактирования ресурсов формы

В панелі інструментів редактора ресурсів заголовок першої кнопки вказує


на той модуль, який зараз відкритий. На рис. 4 відкритий модуль редагування
рядків (кнопка називається Strings). Якщо клацнути стрілку вниз праворуч від
кнопки Strings, то з'явиться спливаюче меню, в якому ви можете вибрати тип
ресурсів, які можна редагувати. Існують наступні типи ресурсів (в дужках вказані
гарячі клавіші для виклику відповідного модуля редагування):

- Strings (<Ctrl> - <1>) - рядки;

- Images (<Ctrl> - <2>) - зображення;

- Icons (<Ctrl> - <3>) - іконки;

- Audio (<Ctrl> - <4>) - аудіозаписи;

- Files (<Ctrl> - <5>) - файли;

- Other (<Ctrl> - <6>)


- щось інше, наприклад, призначені для користувача дані.

Для додавання нового ресурсу такого ж типу, як і відкритий модуль,


досить клацнути по кнопці Add Resource (Додати ресурс) на панелі інструментів-
тов. Щоб вибрати тип ресурсу і метод створення, клацніть по стрілці вниз
праворуч від кнопки Add Resource. У випадаючому меню можна вибрати
створення ресурсу на основі існуючого файлу або зробити вибір типу зображення
для ресурсу типу Image.

2.2. Файл для логіки модуля


Тепер подивимося на вміст файлу Form.css. Якщо двічі клацнути по
ньому, то файл відкриється в режимі візуального дизайну, де ви можете
розставляти компоненти. Щоб побачити код форми, потрібно натиснути клавішу
<F7> або натиснути правою кнопкою миші на ім'я файлу в
панелі Solution Explorer і з контекстного меню вибрати View Code (Показати
код).

На самому початку файлу як завжди знаходиться підключення просторів


імен, які ми можемо використовувати в модулі. Майстер підключив простори
імен з великим запасом, тому що для компіляції коду, який знаходиться зараз в
модулі, досить тільки system і System.windows .Forms. Все інше додано, бо
в Microsoft порахували, що воно вам знадобиться.

Простори імен я опустив, а все інше показано в наступному коді:

namespace OurFirstVisualApplication
{

public partial class Forml : Form


{
public Form1()

{
initializeComponent();

}
}
}
Відразу ж бачимо, що весь код також оголошений в просторі імен
OurFirstvisuaiApplication. Усередині цього простору оголошується відкритий
клас з ім'ям Form1, який є спадкоємцем класу Form. В цьому оголошенні багато
чого цікавого, що ми ще не розглядали.

Для початку потрібно сказати про клас Form. В .NET цей клас реалізує усі
необхідні для форми властивості і методи. Можна створити екземпляр цього
класу і викликати метод відображення, і ви на екрані побачите вікно. Згадайте,
що екземпляр класу форми був переданий методу Run () класу Application. Цей
метод запускає цикл обробки і відображає вікно, так що нам відображати його не
потрібно. Якщо ви будете створювати вікно самі, то його потрібно буде самому і
відображати з допомогою методу Show () АБО ShowDialog (). Такі методи є у
класі Form.

В даному випадку у нас не просто екземпляр класу, а його спадкоємець.


Просто примірника було б достатньо, якби ми просто змінили його властивості і
відобразили. Але чим може бути корисно порожнє вікно? Нічим! Тому ми
створюємо спадкоємця і будемо розширювати його можливості, додаючи меню,
кнопки і панелі, а не просто змінювати властивості.
В принципі, створити форму і накласти на неї компоненти можна і без
наслідування, але мені здається, що такий підхід буде не дуже зручним і
ефективним. Клас повинен бути автономним і має сам розставляти на поверхні
всі необхідні компоненти. Те, що ми можемо поставити компоненти ззовні, не
означає, що це хороший спосіб. При проектуванні класу завжди намагайтеся
робити його автономним і максимально незалежним від зовнішніх факторів.

Дуже цікавим модифікатором на початку оголошення класу є partial. Він


означає, що оголошення класу розбите на кілька файлів з кодом. Перед нами
перший з цих файлів, а забігаючи вперед, скажу, що продовження реалізації класу
знаходиться в файлі Form1.Designer.cs. Це дуже потужна можливість, коли ви
можете розбити реалізацію класу на кілька файлів. Наприклад, в одному файлі ви
реалізуєте усі методи, в іншому - усі властивості, а в третьому оголошуєте
додаткові змінні. Для цього потрібно, щоб у всіх трьох файлах було оголошення
класу з одним і тим же ім'ям і з модифікатором partial.

Усередині класу в файлі Form1.cs визначається тільки конструктор, в


якому викликається метод Initializecomponent (). Що це таке, і звідки взявся цей
метод? У ньому ініціалізувалися усі властивості форми і компоненти, які можуть
бути встановлені на формі. Але де він оголошений і як виглядає? Про це ми
дізнаємося в розд. 2.4.

2.3. Іменування форми


Ми вже говорили, що всі змінні слід назвати зрозумілими словами. Ніяких
імен в стилі Form1 в реальних додатках не повинно бути. Але не можна
перейменовувати просто так змінну класу, особливо, якщо це форма. Тут краще
перейменовувати файл.

Клацніть правою кнопкою миші по імені файлу форми в


панелі Solution Ex-plorer і з контекстного меню виберіть
пункт Rename (Перейменувати). Введіть нове ім'я форми, і будуть перейменовані
не тільки імена файлів, пов'язаних з формою, а й клас, що знаходиться всередині.
При цьому зміни відбудуться у всіх файлах, де задіяна форма, в тому числі і в
файлі Program.cs.

2.4. Код, згенерований дизайнером


Раніше весь код, який стосувався форми, знаходився в одному файлі коду.
Але це було незручно, тому що розмір файлу ріс з божевільною швидкістю, і
управління ним ставало незручним. Зараз середовище розробки розбиває код на
два файли. В одному файлі ми пишемо всю свою логіку (в файлі Form1.cs, який
ми розглянули в розд. 2.2), а в іншому файлі середовище розробки зберігає весь
необхідний код для реалізації того, що ми зробимо візуально в дизайнері.

Ми поки нічого не робили в дизайнері, але давайте подивимося, що вже є


в файлі Forml.Designer.cs. Для цього клацніть по ньому правою кнопкою миші і з
контекстного меню виберіть пункт View Code. Код того, що згенерував дизайнер
в моєму випадку, показаний в лістингу 2.

Лістинг 2. Код файлу Form1.Designer.cs

namespace OurFirstVisualApplication

{
partial class Form1 {
/// Required designer variable.

/// Переменные, необходимые дизайнеру /// </summary>


private System.ComponentModel.IContainer components = null;

/// <summary>

/// Clean up any resources being used.

/// Очистка любых использованных ресурсов /// </summary>


/// <param name="disposing'^true if managed resources should /// be disposed;
otherwise, false.</param> protected override void Dispose(bool disposing)
{
if (disposing && (components null))
{
components.Dispose(); // уничтожить переменную компонентов
}
base.Dispose(disposing); // вызвать метод базового класса
}

#region Windows Form Designer generated code /// <summary>


/// Required method for Designer support - do not modify /// the contents of this
method with the code editor.
/// Метод, который необходим дизайнеру - не изменяйте /// содержимое
метода в редакторе кода /// < /summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1 //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode - System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 264);
this.Name = "Forml";
this.Text = "Forml";
this.ResumeLayout(false);
}

ftendregion
}
}

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

Отже, в файлі Form.Designer.cs йде продовження оголошення


класу Form1. Про це свідчить те, що на самому початку знову йде оголошення
класу Form1 і вказано модифікатор partial. Тобто все, що буде описано в класі
цього модуля, буде додано до конструктора, який ми вже розглянули в розд. 2.2.

На самому початку класу оголошується змінна components, яка є


контейнером для всіх компонентів, які не мають візуального інтерфейсу, т. е. Не
видимі на формі. Так, бувають і такі компоненти, і вони вбудовані в .NET у
вигляді компонентів для зручності програмування.

Далі йде метод Dispose (), який буде викликатися системою, коли
необхідно буде знищити об'єкт класу форми. У загальних рисах скажу, що
відбувається в цьому методі, - викликається метод Dispose () змінної components,
щоб вона почистила за собою, і викликається цей же метод базового класу форми.

Після методу Dispose () починається найцікавіше, а саме, виклик методу


InitializeComponent (). Ви не бачите цього методу? Але ви бачите наступний
рядок, написану сірим кольором:

Windows Form Designer generated code


Якщо так, то клацніть зліва від цього рядка на хрестику, який знаходиться
на полях. Це змусить редактор коду розкрити регіон. Що таке регіон? Це блок
коду, оточений ключовими словами #region ххххх і #endregion, де хххх - це ім'я
регіону. Написавши це в коді, зліва від рядка з #region на полях ви побачите
хрестик, за допомогою якого можна згортати весь код, виділений цими двома
ключовими словами. Звернувши блок коду, ви будете бачити тільки ім'я регіону.

Повернемося до методу InitializeComponent (). Згадайте розд. 2.2, де ми


розглядали конструктор нашої форми. Там ми говорили про те, що в конструкторі
викликається метод з точно таким же ім'ям. Так ось він де знаходиться. І хоча він
реалізований в іншому файлі, він все ж залишається частиною того
ж partial класу.

Незважаючи на те, ЩО назву методу InitializeComponent ()


перекладається як "ініціалізувати компонент", метод ініціалізує властивості
форми, а також створює всі елементи управління, які ми поставимо на форму
візуально. Так, саме візуально і тільки візуально. Ручками в цей метод нічого
писати не рекомендується, інакше дизайнер може виявитися нездатним зрозуміти
ваші благі наміри і ваш мега-код при спробі відкрити форму в дизайнері він
поверне помилку. Якщо й виникне необхідність вносити якісь зміни в
метод InitializeComponent (), то робіть це дуже акуратно і обережно.

Тепер одним оком подивимося, що відбувається всередині цього методу.


На самому початку викликається метод SuspendLayout () для нашої форми (про
те, що викликається метод саме поточної форми, говорить слово this). Цей метод
змушує систему призупинити реагування на зміну атрибутів. Справа в тому, що
при зміні будь-якого атрибуту система буде перемальовувати форму. При
ініціалізації найчастіше доводиться змінювати відразу кілька атрибутів, і після
зміни кожного з них реагувати і змінювати форму невигідно. Набагато
ефективніше змінити всі атрибути, а потім вже хай форма один раз відреагує на
всі зміни і перемалюється відповідно до змін в потрібному місці.

Отже, після виклику методу SuspendLayout () для нашого вікна воно не


буде реагувати і змінювати свою форму при зміні атрибутів, а зробить це після
виклику методу ResumeLayout ().

Далі йде зміна властивостей форми. Ми поки не будемо розглядати ці


властивості, все прийде з часом. Хочу тільки сказати, що середовище розробки і
генератор цього коду мудрі, як ніколи, і допомагають нам, як тільки можливо. У
методі InitializeComponent () з'явиться код для ініціалізації всіх кнопок, які ви
будете мати у своєму розпорядженні на формі, і всіх інших елементів управління,
Щоб простіше було працювати з методом, генератор буде групувати код так, щоб
код ініціалізації одного елемента управління перебував у одному місці, а не
розкиданий по всьому методу InitializeComponent ().

До того ж, перед початком ініціалізації чергового елемента буде йти


коментар, в якому буде вказано ім'я елемента управління, властивості якого
будуть далі змінюватися. У нашому прикладі немає нічого крім форми, але,
незважаючи на це, перед початком зміни її властивостей стоїть коментар. Спасибі
розробникам Visual Studio зате, що не забувають про нас.

2.4. Hello Visual World


Тепер можете запустити програму за допомогою клавіші <F5>, як ми це
робили у випадку з консольними додатками. На екрані має з'явитися вікно таких
же розмірів, які були в вікні дизайнера.

Рисунок 5. Панель Properties з властивостями форми

Щоб наш приклад став повноцінним додатком "Hello World", з


візуальним вікном, давайте змінимо заголовок вікна. Для цього потрібно
переключитися на візуальну форму, що можна зробити декількома способами,
наприклад просто клацнути двічі по імені файлу Forml.cs в
панелі Solution Explorer. За замовчуванням форми з візуальним інтерфейсом
відкриваються саме в візуальному дизайнері. Якщо у вашому середовищі
розробки сталося не так, то можна натиснути правою кнопкою миші по імені
файлу і із контекстного меню вибрати View Designer (Показати дизайнер). Якщо
ви перебуваєте у вікні коду, можна натиснути комбінацію клавіш <Shift> - <F7>.

У дизайнері повинна бути обрана форма, тоді в панелі Properties з'являться


властивості форми (рис. 5). В принципі, у нас нічого крім форми немає, тому, все
одно будуть відображатися властивості саме форми, але головне, щоб панель
Properties була присутня на екрані. Якщо ви її не бачите, виберіть в головному
меню View | Properties Window.

В панелі Properties в лівому стовпчику знайдіть властивість Text і


навпроти нього змініть в правій колонці назву заголовка на "Hello world" (за
замовчуванням воно дорівнює імені класу). Ось тепер можна запускати додаток
знову і спостерігати в заголовку вікна велику фразу, з якої починали вчитися
програмуванню багато знаменитих програмістів.

Ми зробили невелику зміну, але вона дуже важлива для нас, тому що ми
дізналися, як працювати з властивостями в візуальному дизайнері, і навчилися
змінювати їх значення. Тепер можете повернутися в файл Form1.Designer.es і
подивитися на метод ініціалізації компонентів. Зверніть увагу на наступний
рядок коду:

this.Text = "Hello World";


У відповідь на зміну в візуальному дизайні середовище розробки
згенерувало відповідний код. Ми могли б ручками написати цей же код, адже тут
просто властивості Text поточного об'єкта присвоюється рядок, але через
візуальний дизайнер було цікавіше і простіше.

3. Властивості форми
Ми вже побачили, що властивості можуть змінюватися як візуально, так і
програмно. Візуальні зміни дизайнер оформляє в коді методу InitializeComponent
(). Якщо ви вирішили самі робити зміни властивостей в коді, то це можна зробити
в конструкторі і обов'язково після виклику методу InitializeComponent (). Якщо
написати код змін до виклику цього методу, то вони можуть виявитися марними,
якщо дизайнер згенерує свій код в методі ініціалізації компонентів.

Відкрийте зараз код форми (Form.css) і спробуйте в коді конструктора


привласнити властивості Text поточної форми якесь значення, наприклад, як
показано в наступному прикладі:

public Form1()
{
InitializeComponent() ;

Text = "Це змінено в коді";


}
Відкрийте програму і переконайтеся, що в заголовку вікна відображається
нове повідомлення. Давайте повернемося в візуальний дизайнер і подивимося,
що ще у нас є в панелі Properties. Там дуже багато властивостей, і всі вони
успадковуються нашою формою від класу Form. Ми можемо наділити форму
додатковими властивостями, але у нас і так достатньо успадкованого, з чим
потрібно ще розібратися. Ми будемо розглядати в міру потреби ті властивості,
які будуть нам потрібні. Зараз же обмежимося тільки найосновнішими і
найнеобхіднішими:
- Background Color - колір фону вікна. Дана властивість має тип класу
Color. Якщо клацнути в полі навпроти властивості, то з'явиться кнопка списку.
Клацніть по ній, і ви побачите панель вибору кольору, як на рис. 6.

Рисунок 6. Панель вибору кольору

Панель складається з трьох закладок: Custom (Довільні), Web (Web-


кольори) і System (Системні). Для вікон бажано вказувати один із системних
кольорів і краще, якщо це буде control для діалогових вікон і Window для вікон,
які повинні відображати дані;

- Cursor - дозволяє задати курсор, який буде відображатися в момент, коли


курсор миші знаходиться над поверхнею вікна. При зміні цієї властивості в
візуальному дизайнері з'являється випадаючий список, в якому перераховані
назви типів курсорів і навіть показані їх зображення;

- Enabled - дозволяє задати доступність вікна. Якщо властивість рівна


false, то компонент не реагуватиме на дії користувача, буде недоступний;

- Font - шрифт, який буде використовуватися для виведення тексту поверх


вікна. Для вікна це на перший погляд не дуже актуально. Але велика актуальність
цієї властивості проявляється у компонентів, які містять написи. Щоб змінити
шрифт, можна піти двома шляхами:

- виділити рядок з властивістю Font, і в правому кутку з'явиться кнопка з


трьома крапками. Клацніть по ній, і ви побачите стандартне вікно завдання
властивостей шрифту;

- властивість шрифту насправді є самостійним класом Font зі своїми


властивостями. Ви можете редагувати їх кожну окремо. Для цього потрібно
клацнути по кнопці з хрестиком зліва від імені властивості. У вікні Properties
властивості форми розсунуться, поступившись місцем властивостями шрифту
(рис. 7);

Рисунок 7. Властивості для налаштування властивостей шрифту

- ForeColor - колір переднього плану, який найчастіше використовується в


якості кольору тексту. Якщо ви подивитеся на доступні властивості шрифту, то
помітите, що серед них немає кольору. Колір тексту задається через ForeColor;

- FormBorderstyle - стиль контуру форми. Ця властивість є переліком, і в


редакторові властивостей з'являється випадаючий список для вибору із
наступних елементів (рекомендую на реальному додатку спробувати встановити
кожну із властивостей і подивитися результат особисто):

- None - контуру не буде;

- FixedSingle - тоненький фіксований контур, який не дозволяє змінювати


розміри вікна;

- Fixed3D- контур фіксований, який дозволить змінювати розміри вікна,


але тривимірний, що створює ефект утоплення вікна;

- FixedDialog - схожий на FixedSingle, тільки в заголовку вікна не буде


іконки. Такий контур найчастіше використовують для діалогових вікон;

- Sizable - стандартний контур, що дозволяє змінювати розміри вікна;


- FlxedToolWindow- контур з дуже тоненьким заголовком вікна, що не
дозволяє змінювати розміри вікна. Такі вікна найчастіше використовуються для
вікон з кнопками, наприклад вікно інструментів в Abode Photoshop;

- SizableToolWindow- те ж саме, що І FixedToolWindow, тільки з


можливістю змінювати розмір вікна;

- Icon - в цій властивості можна задати іконку для форми. Тут теж є кнопка,
яка викликає стандартне вікно для відкриття файлу. Завантажена іконка
потрапить до resx-файлу форми;

- Location - положення вікна відносно лівого верхнього кута екрану. Така


ж властивість є і у компонентів, але там відстань відраховується від лівого
верхнього кута компонента батька, на поверхні якого знаходиться наш елемент
керування. Дана властивість складається з двох складових - х та у, які
розкриваються, якщо клацнути по кнопці з хрестиком зліва від імені властивості;

- MainMenuStrip- в цій властивості можна задати компонент меню, який


буде використовуватися в якості головного меню для вікна. Для цього на формі
повинен стояти компонент класу MenuStrip. Тоді цей компонент можна буде
вибрати зі списку;

- MaximizeBox- логічне значення, яке визначає, чи повинна відображатися


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

- MaximumSize- дозволяє задати максимальні ширину та висоту вікна.


Користувач не зможе розтягнути вікно більше, ніж зазначені розміри;

- MinimizeBox- логічне значення, що визначає, чи потрібно відображати


кнопку згортання вікна;

- Minimum Size- мінімальні розміри вікна, менше яких вікно не може бути
зменшено. Таке обмеження може стати в нагоді, якщо занадто маленькі розміри
псують дизайн вікна;

- Name - назва форми та ім'я змінної об'єкту, яку ви можете


використовувати в коді для доступу до властивостей об'єкта та для виклику його
методів;
- Opacity- відсоток прозорості вікна. За замовчуванням властивість
дорівнює 100%. Вікно абсолютно непрозоро. Якщо потрібно наполовину
просвітити задній план, то можна встановити значення в 50%;

- Padding- відступи від країв вікна. Властивість складається з п'яти


значень: Аll, Left, Toр, Right, Bottom, що відповідає відступами з усіх боків, зліва,
зверху, праворуч та знизу. Якщо встановити відступ зліва в значення 10, то ліва
кромка вікна буде розміром в 10 пікселів;

- Show Icon - логічне значення, що визначає, чи потрібно показувати


іконку в заголовку вікна;

- ShowInTaskBar - чи потрібно відображати вікно в панелі завдань.


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

- Size - розмір вікна, його ширина та висота;

- StartPosition- початкова позиція вікна. У цієї властивості є випадаючий


список для вибору одного із наступних значень:

- windowsDefaultLocation - положення вікна визначається ОС;

- windowsDefault Bounds - система визначатиме не тільки положення, але


і розміри вікна;

- CenterParent - розташувати вікно по центру батьківського вікна. На мій


погляд, це значення найкраще використовувати для всіх дочірніх вікон;

- Manual - розташування буде задаватися програмістом самостійно, через


властивість Location;

- CenterScreen - відцентрувати по центру екрана;

- Tag - дуже цікава властивість, але вона абсолютно ні на що не впливає.


Проте навіщо тоді вона потрібна? Ви можете зберігати в цій властивості будь-яку
додаткову інформацію, тому що це властивість має тип object;

- Text - текстовий заголовок вікна


- TopMost - логічне значення, яке визначає, чи має вікно розташовуватися
поверх інших вікон. Відразу хочу попередити - не зловживайте цією властивістю
в своїх програмах для головного вікна, а якщо і вирішите розташувати вікно
поверх інших, то дайте користувачу можливість відключати цю особливість.
Багатьох користувачів дратують вікна, які перекривають робочу область. А ось
використання цієї властивості для дочірніх вікон програми може бути дуже
зручним. Якщо вікно показано модально, ця властивість дозволить вікну бути
поверх інших і не сховатися за іншими вікнами;

- WindowState - стан вікна. Тут можна вказати одне з трьох значень:

- Normal - нормальний стан;

- Maximized - вікно повинно бути розгорнуто на весь екран;

- Minimized - вікно повинно бути мінімізовано.

Нагадую, що наші лкції - не довідник по функціях, такий довідник вже є,


і називається він MSDN. Ми розглядаємо тільки найцікавіше і вчимося
програмувати.

Чому я розглянув ці властивості? Більшість з них є не тільки у форм, а й у


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

Тепер давайте подивимося, що приховують під собою кнопки з хрестами


зліва від деяких властивостей. Хрестики можуть стояти у тих властивостей, які
самі по собі є об'єктами певного класу. Наприклад, властивість Font є класом
Font. Розкриваючи хрестик у властивості Font, ви побачите властивості класу
Font. Наприклад, розкривши шрифт Font, ви можете побачити властивість size -
розмір. Поний шлях до розміру шрифту буде виглядати так:

Control.Font.Size = 10;
У цьому прикладі розмір шрифту змінюється на 10. Для цього ми
змінюємо властивість size об'єкта класу Font, який є властивістю нашого
елементу управління. Може існувати і довша вкладеність, але в C # я не пригадую
вкладеності більше 5, та й більше 3-х зустрічається вкрай рідко. Коли ви самі
будете проектувати ваші програми і класи, не робіть вкладеності більше 4, інакше
це можуть бути просто не дуже добре спроектовані класи, а робота з ними буде
незручна і навіть жахлива.
Відразу ж слід розглянути структури даних, з якими ви будете
зустрічатися при роботі з компонентами і формами: Size і Location. Розглянемо
кожну окремо.

Структура size призначається для завдання розмірів, наприклад розмірів


компонента або форми. У структури є два поля - width і Height - для вказівки
ширини і висоти відповідно. Ви не можете змінювати властивості структури, і
наступний рядок призведе до помилки компіляції:

Size.Height = 100;
Завжди потрібно створювати новий екземпляр структури. Наприклад,
наступний приклад встановлює розміри вікна в 200x300:

Size = new Size(200, 300);


Тип даних Size використовується також ДЛЯ ВЛАСТИВОСТЕЙ
Maximum Size, Minimum Size, AutoScrollMargin І AutoScrollMinSize.

Структура Location має тип Point. І судячи з назви, з її допомогою


найчастіше задають точку. Наприклад, цей тип використовується для завдання
положення когось компонента або форми. Ця структура містить два важливих
властивості - х і у, які зберігають зміщення по відповідним координатним осям.
Наступний рядок переміщує поточну форму в позицію 10x10;

this.Location - new Point(10, 10);


У обох структур властивості, які визначають розмір і положення, мають
тип даних цілого числа int. Ви не можете задати дробове число в якості
положення, та це й не має сенсу в WinForms, адже розміри форми і положення
визначаються пікселями, а це мінімальна одиниця в даному випадку, і вона не
може ділитися.

4. Методи форми
Клас Form містить безліч методів, які ми можемо використовувати і які
успадковуються нашими формами:

- Show() -Відобразити створене вікно немодальним. Немодальне вікно не


блокує виконання батьківського вікна (в якому воно було створено). Це означає,
що обидва вікна будуть працювати як би паралельно. Ви можете перемикатися
між ними і працювати в двох вікнах одночасно;

- ShowDialog () - відобразити вікно модально. У цей момент у вікні, в


якому ви викликали метод, виконання блокується до тих пір, поки ви не закриєте
дочірнє вікно, яке відобразили за допомогою ShowDiaiog (). Ви можете
працювати тільки з дочірнім вікном, і воно завжди відображається поверх свого
батьківського вікна. Таким чином відображаються всі діалогові вікна, наприклад
вікно відкриття документа, вікно властивостей і т.д.;

- Hide () - заховати вікно, не знищуючи його. Ця дія має сенс для


немодальних вікон, які не блокують батьківське вікно; close () - закрити форму.
При закритті форми її об'єкт знищується;

- Invalidate () - Перемалювати форму.

Методи ми також будемо розглядати в міру потреби, а поки цього


достатньо.

5. Події на прикладі форми


У платформі .NET, як і в Win32, для інформування про виникнення
якогось стану або про дію використовуються події, або іноді їх ще називають
повідомлення (по-англійськи events). Наприклад, у відповідь на зміну положення
вікна воно генерує подію певного класу, яку ми можемо перехопити.

Для того щоб перехопити подію, потрібно створити її обробник.


Обробник події по суті є методом, який реєструється на відловлювання певної
події від певного елемента управління / форми / компонента. Коли настане подія,
то цей самий елемент управління / форма / компонент викличе метод, в якому ми
можемо написати код реакції на подію.

За допомогою візуального дизайнера Visual Studio створення обробників


подій перетворюється в тривіальну задачу. На рис. 8 показана панель Properties в
режимі перегляду подій. Щоб побачити щось подібне, потрібно виділити
компонент, подію якого ви хочете зловити, і натиснути кнопку Events в панелі
Properties (на рис. 8 ця кнопка виділена колом). Щоб повернутися назад до
перегляду властивостей, потрібно клацнути по кнопці Properties, яка знаходиться
лівіше.

Тепер, щоб створити потрібний обробник події, досить двічі клацнути в


полі одразу після назви події. Середовище розробки створить необхідну подію,
додасть її реєстрацію У своєму методі InitializeComponent (), переключиться в
режим коду і встановить курсор в тіло методу, створеного для обробки події.

Давайте створимо обробник події Mouse Click. Виділіть форму, перейдіть


в панель Properties в режим перегляду подій Events і двічі клацніть напроти події.
Буде створено метод Form1_MouseClick ():

MessageBox.Show("Клац");

Рисунок 8. Панель Properties під час перегляду подій


private void Form1_MouseClick(object sender, МоuseEventArgs e)
{
}

Я тут додав всередину методу обробки події виклик статичного


методу show () класу MessageBox. Цей метод відображає на робочому
столі діалогове вікно з повідомленням, яке ви передали в якості
параметра. У нашому випадку кожен раз, коли ви будете клікати по формі,
буде з'являтися повідомлення "Клік".
Дуже цікавим є питання про те, які події отримали форма, коли
з'являється і знищується. При завантаженні форми генеруються наступні
події і саме в такій послідовності:
- Load - завантаження;
- Activate - активація;
- VisibleChanged - змінилася властивість Visible.
А під час закриття форми генеруються наступні події:
- Deactivated - деактивовано;
- Closing - закриття форми (можна скасувати закриття);
- Close - форма закрита, і назад дороги немає.
Подія Load генерується, коли ви вперше викликається метод Show
() для відображення форми. Подивимося на наступний приклад:
MyForm form = new Form ();
form.Show (); // Відобразити форму
form.Hide (); // Заховати за допомогою Hide ()
form.Show (); // Показати знову
Подія Load буде згенеровано тільки під час першого виклику методу
Show (), тому що в цей момент буде відбуватися завантаження форми.
Коли ми викликаємо метод Hide (), то форма залишається завантаженою,
просто ховається з екрану. Наступний виклик методу show () тільки змінює
видимість вікна, а завантаження не буде, тому і подію Load більше
генеруватися не буде.
Дуже часто у вас будуть виникати казуси з випадковим створенням
подій. Наприклад, якщо двічі клацнути по компоненті в візуальному
дизайнері, то буде створений обробник події за замовчуванням для цього
компонента. Для кнопки подією за замовчуванням є click, і якщо ви
випадково двічі клацнете по компоненті в візуальному дизайнері, то буде
створений цей обробник події. А якщо ви не хотіли його створювати?
Залишати заготовку методу в коді? Напевно краще все ж прибрати
обробник події, щоб він не заважав. Як це зробити? Існує кілька варіантів:
1. Виділіть компонент в візуальному дизайнері і перейдіть в режим
Events в панелі властивостей. Напроти події видаліть в полі назву
методу, створеного для обробника події. Візуальний редактор
видалить реєстрацію події, яку він автоматично додав до свого метод
InitializeComponent (). Якщо в обробнику події не було коду, то
заготовка для методу зникне і з коду.
2. Якщо обробник події містить код, але він вже не потрібен, то можна
спочатку видалити код з обробника події, а потім виконати дії з пункту
1.
3. Якщо обробник події містить код, то можна спочатку видалити ім'я
обробника події в режимі Events панелі властивостей, а потім
безболісно видалити код методу.
4. Якщо ви створили обробник події і тут же видалили метод в
редакторі коду, то при цьому середовище розробки не видалить
реєстрацію події в методі InitializeComponent (). Це доведеться
робити вручну. Як це зробити безболісно? Давайте подивимося на
прикладі.
private void button1_Сlick(object sender, EventArgs e)
{
}

Видаліть цю заготовку кода з редактора і спробуйте скомпілювати


проект. У цій помилці компілятор повідомляє нам, що обробник події не
знайдено. Двічі клацніть по помилці, і відкриється закладка з файлом
(Forml.Designer.es), де знайдена помилка, і буде виділено рядок кода, яку
додав візуальний редактор для реєстрації події, для того, щоб позбутися
від помилки, потрібно видалити рядок, яку виділив нам редактор. Таким
чином, ви вручну видалите реєстрацію, і проект відкомпілюйте без
проблем.

You might also like