134
1 Міністерство освіти і науки України Запорізька державна інженерна академія ОБ’ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ Методичні вказівки до виконання лабораторних робіт для студентів ЗДІА спеціальності 080403 ”Програмна інженерія” очної та заочної форм навчання

метуказлабраб ооп 2011укр

  • Upload
    -

  • View
    400

  • Download
    13

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: метуказлабраб ооп 2011укр

1

Міністерство освіти і науки України

Запорізька державна інженерна академія

ОБ’ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ

Методичні вказівки

до виконання лабораторних робіт

для студентів ЗДІА

спеціальності 080403 ”Програмна інженерія”

очної та заочної форм навчання

Page 2: метуказлабраб ооп 2011укр

2

Об’єктно-орієнтоване програмування. Методичні вказівки до виконання лабораторних робіт. Для студентів ЗДІА спеціальності 080403 ”Програмна інженерія” очної та заочної форм навчання /Укл.: В.І.Попівщий. – Запоріжжя, 2011. – 135 с.

Методичні вказівки призначені для студентів спеціальності 080403 ”Програмне забезпечення автоматизованих систем”, які виконують лабораторні роботи по курсу “Об’єктно-орієнтоване програмування ”. Вказівки містять завдання для лабораторних робіт, теоретичні відомості, зразки виконання завдань, список рекомендованої літератури.

Укладач: В.І.Попівщий, доцент

Відповідальний за випуск : зам.зав.кафедрою ПЗАС

доцент А.І.Безверхий

Page 3: метуказлабраб ооп 2011укр

3

ЗМІСТ

ВСТУП ........................................................................................................................................................ 5

Лабораторна робота №1. Введення в C#. Створення консольних застосувань і застосувань

Windows Forms на C# в Visual Studio 2005. Робота з вбудованими (примітивними) типами

даних. Оператори вибору. ....................................................................................................................... 7 Завдання. ............................................................................................................................................................ 7 Хід роботи. ........................................................................................................................................................ 8 Вправа 1. Створення консольного застосування на C# в середовищі Visual Studio 2005. ......................... 8 Вправа 2. Створення застосування Windows Forms. ................................................................................... 10 Методичні вказівки і теоретичні відомості. ............................................................................................... 15

Що таке .NET Framework .................................................................................................................................................. 15 Архітектура середовища виконання .NET ....................................................................................................................... 16 Загальна бібліотека класів ................................................................................................................................................ 18 Типи даних C# .................................................................................................................................................................... 19 Введення даних користувачем і їх виведення ................................................................................................................. 20 Вказівки до завдання 3. ..................................................................................................................................................... 21 Вказівки до завдання 4. ..................................................................................................................................................... 21

Лабораторна робота №2. Цикли, рядки, файли в C#. ...................................................................... 25 Завдання. .......................................................................................................................................................... 25 Хід роботи. ...................................................................................................................................................... 26 Вправа 1. Використання класу FileStream для читання з файлу з довільним доступом .......................... 26 Вправа 2. Відрядкове читання з файлу за допомогою класу StreamReader ............................................... 27 Методичні вказівки і теоретичні відомості. ............................................................................................... 27

Цикли .................................................................................................................................................................................. 27 Робота з рядками і символами .......................................................................................................................................... 30 Робота з файлами ............................................................................................................................................................... 33 Вказівки до завдання 1. ..................................................................................................................................................... 35

Лабораторна робота №3. Обробка виключень в C#......................................................................... 36 Завдання. .......................................................................................................................................................... 36 Хід роботи. ...................................................................................................................................................... 36 Вправа 1. ........................................................................................................................................................... 36 Вправа 2. ........................................................................................................................................................... 37 Методичні вказівки і теоретичні відомості. ............................................................................................... 38

Клас System.Exception ....................................................................................................................................................... 38 Основи обробки виключень .............................................................................................................................................. 38

Лабораторна робота №4. Використання масивів і колекцій. Класи ArrayList, Queue, Stack,

Hashtable, SortedList. .............................................................................................................................. 40 Варіанти завдання. ......................................................................................................................................... 40 Хід роботи. ...................................................................................................................................................... 41 Вправа 1. ........................................................................................................................................................... 41 Вправа 2. ........................................................................................................................................................... 42 Методичні вказівки і теоретичні відомості. ............................................................................................... 44

Масиви ................................................................................................................................................................................ 44 Робота з колекціями........................................................................................................................................................... 46

Лабораторна робота №5. Класи в C#. Спадкування. ....................................................................... 53 Варіанти завдання. ......................................................................................................................................... 53 Хід роботи. ...................................................................................................................................................... 53 Вправа 1. ........................................................................................................................................................... 54 Вправа 2. ........................................................................................................................................................... 54 Методичні вказівки і теоретичні відомості. ............................................................................................... 55

Визначення класу ............................................................................................................................................................... 56 Спадкоємство ..................................................................................................................................................................... 60 Віртуальні методи .............................................................................................................................................................. 64

Лабораторна робота №6. Перевантаження операцій в C#. ............................................................. 65 Варіанти завдання. ......................................................................................................................................... 65 Хід роботи. ...................................................................................................................................................... 67

Page 4: метуказлабраб ооп 2011укр

4

Вправа. Клас Fraction раціональних чисел (дробів). .................................................................................... 68 Методичні вказівки і теоретичні відомості. ............................................................................................... 70

Основи перевантаження операцій .................................................................................................................................... 70 Перевантаження бінарних операцій ................................................................................................................................. 71 Перевантаження унарних операцій .................................................................................................................................. 71

Лабораторна робота №7. Делегати і події. ......................................................................................... 72 Варіанти завдання. ......................................................................................................................................... 72 Хід роботи. ...................................................................................................................................................... 72 Вправа 1. ........................................................................................................................................................... 72 Вправа 2. ........................................................................................................................................................... 74 Методичні вказівки і теоретичні відомості. ............................................................................................... 75

Делегати .............................................................................................................................................................................. 75 Події .................................................................................................................................................................................... 77

Лабораторна робота №8. Використання елементів Windows Forms і діалогових вікон. .......... 79 Варіанти завдання. ......................................................................................................................................... 79 Хід роботи. ...................................................................................................................................................... 87 Вправа 1. Приклад використання меню ........................................................................................................ 87 Вправа 2. Побудова призначених для користувача діалогових вікон ......................................................... 89 Методичні вказівки і теоретичні відомості. ............................................................................................... 91

Лабораторна робота №9. Виведення графічної інформації. GDI+. ............................................. 109 Варіанти завдання. ....................................................................................................................................... 109 Хід роботи. .................................................................................................................................................... 109 Вправа 1. Виведення ліній за допомогою класу Pen.................................................................................... 110 Вправа 2. Малювання фігур за допомогою класу Brush ............................................................................. 110 Вправа 3. Малювання квадратів по натисненню лівої кнопки миші ........................................................ 112 Методичні вказівки і теоретичні відомості. ............................................................................................. 113

Лабораторна робота №10. Доступ до даних за допомогою ADO.NET. ........................................ 117 Завдання. ........................................................................................................................................................ 117 Хід роботи. .................................................................................................................................................... 117 Короткі теоретичні відомості. ................................................................................................................. 120

Лабораторна робота №11. Застосування ASP.NET . ...................................................................... 123 Завдання. ........................................................................................................................................................ 123 Хід роботи. .................................................................................................................................................... 123 Вправа. ............................................................................................................................................................ 123 Короткі теоретичні відомості. ................................................................................................................. 133

ЛІТЕРАТУРА ........................................................................................................................................ 134

Page 5: метуказлабраб ооп 2011укр

5

ВСТУП

Не буде перебільшенням сказати, що мова C# та пов'язане з нею середовище, платформа .NET, є найбільш важливою новою технологією для розробників за останні роки [1]. C# (вимовляється “сі шарп”) – об'єктно-орієнтована мова програмування для платформи .NET. Вона розроблена Андерсом Хейлсбергом, Скоттом Вілтамутом і Пітером Гольде під егідою Microsoft Research (науково-дослідний інститут при фірмі Microsoft) [28]. Андерс Хейлсберг (Anders Heilsberg) – творець TurboPascal і головний архітектор Delphi (до версії 4.0).

Мова C#, разом з Visual Basic .NET, Visual C++.NET скриптовою мовою JScript .NET входить до складу Microsoft Visual Studio .NET. Всі ці мови забезпечують доступ до платформи Microsoft .NET (раніше ця платформа називалася Next Generation Windows Services NGWS), яка містить загальне виконуюче ядро і обширну бібліотеку класів.

Синтаксис C# близький до синтаксису С++ і Java. Мова має строгу типізацію, підтримує поліморфізм, перевантаження операторів, делегати, події, властивості, виключення, коментарі у форматі XML і автоматичну “збірку сміття”. Мова не підтримує множинного спадкоємства і , в першій версії, - узагальненого програмування (як в С++). Коріння мови C# йде від мови C++, Delphi, Модула, Smalltalk, Java, хоча вона запозичила багато речей і з інших мов.

C# – прямий нащадок двох найуспішніших в світі комп'ютерних мов: С і С++ [9]. Від C вона успадкувала синтаксис, ключові слова і операції. Вона дозволяє побудувати і удосконалити об'єктну модель, визначену в C++. Крім того, C# близько пов'язана з іншою дуже успішною мовою: Java. C# і Java – це скоріше “двоюрідні брати“[9]. Наприклад, вони обидві підтримують програмування розподілених систем і обидві використовують проміжний код для досягнення переносимості, але розрізняються при цьому в деталях реалізації.

Спираючись на могутній фундамент, який складають успадковані характеристики, C# містить ряд важливих нововведень, що піднімають мистецтво програмування на новий ступінь. Наприклад, до складу елементів мови C# включені такі поняття, як делегати, властивості, індексатори і події. Доданий також синтаксис, який підтримує атрибути; спрощено створення компонентів за рахунок виключення проблем, пов'язаних з СОМ (Component Object Model – модель компонентних об'єктів Microsoft – стандартний механізм, що включає інтерфейси, за допомогою яких об'єкти надають свої служби іншим об'єктам). І ще. Подібно Java, мова C# пропонує засоби динамічного виявлення помилок, забезпечення безпеки і керованого виконання програм. Але, на відміну від Java, C# дає програмістам доступ до покажчиків [9]. Таким чином, C# поєднує первозданну потужність C++ з типовою безпекою Java, яка забезпечується наявністю механізму контролю типів і коректним використанням шаблонних класів. Більш того, мова C# відрізняється тим, що компроміс між потужністю і надійністю ретельно збалансований і практично прозорий (не помітний для користувача або програми).

Програми на C# можуть бути трансльовані в особливий байт-код, що виконується на віртуальній машині – програмі, що обробляє байтовий код і передає інструкції устаткуванню, як інтерпретатор, але з тією відмінністю, що байтовий код на відміну від тексту обробляється значно швидше.

З погляду маркетингу, C# є симетричною відповіддю на виклик з боку компанії Sun Microsystems, що випустила мову Java на декілька років раніше, яка в даний час є основним конкурентом C# на стороні серверних і клієнтських платформ.

Мова C# стандартизована в комітеті ECMA (Європейській асоціації виробників комп'ютерів – Standard ECMA-334° C# Language Specification, 2nd edition, December 2002) і ISO (ISO/IEC 23270:2003, Information technology — C# Language Specification). В даний час випущена друга версія мови, причому до комісії з проектування підключилося ще декілька видних фахівців, серед яких Ерік Майер. Ведуться роботи над третьою версією мови.

Page 6: метуказлабраб ооп 2011укр

6

На думку деяких аналітиків, застосування мови обмежене тим, що вона призначена виключно для платформи .NET фірми Microsoft, і, отже, для операційних систем цієї компанії. Microsoft негативно відноситься до розробки аналогів .NET сторонніми виробниками для інших операційних систем, таких як Mono (для платформи Linux)[28].

Впродовж всієї історії розвитку обчислювальної техніки еволюція мов програмування означала зміну обчислювального середовища, способу мислення програмістів і самого підходу до програмування. Мова C# не є виключенням. У безперервному процесі удосконалення, адаптації і впровадження нововведень C# в даний час знаходиться на передньому краю. Це – мова, ігнорувати існування якої не може жоден професійний програміст [9].

Пропонований цикл лабораторних робіт охоплює основні конструкції мови C# і її застосування при розробці консольних і графічних застосувань Windows, частково стосуючись застосувань ASP.NET та ADO.NET.

Page 7: метуказлабраб ооп 2011укр

7

Лабораторна робота №1. Вступ до мови C#. Робота з вбудованими

(примітивними) типами даних. Оператори вибору.

Мета роботи: набути навичок створення консольних і графічних застосувань на мові C# в середовищі Microsoft Visual Studio 2005.

Завдання.

1. Розробити консольну програму, що виводить меню з пропозицією вибрати один з примітивних типів даних (int, long, float, double, decimal, string, char, bool). Після вибору користувачем певного пункту меню програма повинна видати довільне значення змінної вибраного типу. При виборі пункту Quit здійснити вихід з програми.

2. Розробити графічний варіант попереднього завдання. Програма повинна видавати вікно приблизно такого вигляду:

3. Розробити консольний і графічний варіанти простого калькулятора.

Page 8: метуказлабраб ооп 2011укр

8

4. Розробити застосування Dates, що порівнює дві введені дати. Використовувати умовні оператори і елемент управління DateTimePicker. Написати метод dateCompare. Зразковий вид застосування наступний:

Хід роботи.

1. Виконати Вправу 1 по створенню консольного застосування на C# в середовищі Visual Studio 2005.

2. Виконати Вправу 2 по створенню застосування Windows Forms на C# в середовищі Visual Studio 2005.

3. Виконати завдання 1-4.

Вправа 1. Створення консольного застосування на C# в середовищі Visual Studio 2005.

1. У Microsoft Windows клацніть кнопку Пуск, виберіть Всі програми а потім Microsoft Visual

Studio 2005.

2. Клацніть піктограму Microsoft Visual Studio 2005. Запуститься Microsoft Visual Studio 2005.

3. У меню File виберіть New а потім Project. Відкриється діалогове вікно New Project. Це діалогове вікно надає вам можливість створити новий проект з використанням різних шаблонів, таких як Windows Application, Class Library, або Console Application.

4. У панелі Project types виберіть Visual C#, Window. У панелі Templates виберіть Console

Application.

5. У полі Location виберіть робочий каталог, в якому ви зберігатимете проекти C#.

6. У полі Name надрукуйте TextHello.

7. Переконайтеся в тому, що прапорець Create Directory for Solution вибраний і клацніть OK. Відкриється новий проект. Головне вікно проекту містить звичайні menu bar і toolbar, а також вікна Code and Text Editor window, Solution Explorer і Properties. У вікні Code and Text

Editor відображаються початкові тексти файлів проекту. Вікно Solution Explorer відображає імена файлів і каталогів, пов'язаних з проектом. Перш ніж написати код програми

Page 9: метуказлабраб ооп 2011укр

9

розглянемо файли і директорії в Solution Explorer, створені Visual Studio 2005 як частина проекту.

• Файл рішення (solution) TextHello.sln.

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

• Файл проекту TextHello.csproj.

Кожен файл проекту посилається на один або більше файлів, що містять початкові тексти і інші частини проекту. Всі початкові тексти в одиночному (single) проекті повинні бути написані на одній і тій же мові програмування. Цей файл називається TextHello.csproj.

• Properties.

Це директорія в проекті TextHello. Якщо ви відкриєте її, ви побачите, що вона містить файл AssemblyInfo.cs. Це спеціальний файл, який ви можете використовувати, щоб додати атрибути (attributes) в програму, наприклад такі, як ім'я автора, дата створення програми і т.д.

• References.

Це директорія, яка містить посилання на компільований код, який ваше застосування може використовувати. Коли код відкомпілювався, він перетвориться в assembly і отримує унікальне ім'я. Розробники використовують assemblies щоб упакувати написані ними корисні порції коду для розповсюдження серед інших розробників.

• Program.cs

Це файл початкового коду C#, що відображається в редакторові Code and Text Editor,

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

8. Написання коду з використанням технології IntelliSense.

Page 10: метуказлабраб ооп 2011укр

10

У цій вправі ми напишемо код, що виводить повідомлення Hello World в консольному вікні. У вікні Code and Text Editor відображається файл Program.cs. Помістіть курсор в метод Main

після дужки, що відкривається, і надрукуйте Console. Як тільки ви надрукуєте букву C слова Console, з'явиться список IntelliSense list. Цей список містить всі ключові слова C# і типи даних, які підходять для поточного контексту. Ви можете або продовжити набір на клавіатурі ключового слова Console, або знайти його в списку і виконати на нім подвійне клацання мишею. Відмітимо, що Console є вбудованим класом, що містить методи для відображення інформації на екрані і здійснення введення з клавіатури. Тепер метод матиме наступний вигляд:

static void Main(string[] args) { Console }

9. Надрукуйте крапку відразу після слова Console. З'явиться інший Intellisense list, що відображає методи, властивості і поля класу Console.

10. Знайдіть в списку метод WriteLine і натисніть Enter. Intellisense list закриється і метод буде доданий в початковий файл. Метод Main зараз виглядатиме так:

static void Main(string[] args) { Console.WriteLine }

11. Надрукуйте відкриваючу дужку. З'явиться інший Intellisense tip. Він відображатиме параметри методу WriteLine. Насправді, WriteLine є перевантажуваний метод, і це означає, що існує декілька методів з ім'ям WriteLine, що відрізняються набором параметрів.

12. Надрукуйте закриваючу дужку і крапку з комою. Метод Main зараз виглядатиме так:

static void Main(string[] args) { Console.WriteLine(); }

13. Надрукуйте рядок "Hello World" між дужками, що відкриваються і закриваються. Метод Main зараз виглядатиме так:

static void Main(string[] args) { Console.WriteLine(“Hello World”); }

Побудова і запуск консольного застосування.

14. У меню Build виберіть пункт Build Solution. Ця дія викликає компіляцію коду C#. З'явиться Output window під вікном Code and Text Editor. (Якщо це вікно не з'явилося, то виберіть в меню View пункт Output для відображення цього вікна). Вікно Output відображає результати компіляції і всі деталі, що стосуються помилок, допущених при компіляції.

15. У меню Debug виберіть пункт Start Without Debugging. З'явиться вікно Command window і програма запуститься на виконання. З'явиться повідомлення Hello World, і програма чекатиме натиснення на будь-яку клавішу.

Вправа 2. Створення застосування Windows Forms.

До цих пір ви використовували Visual Studio 2005 для створення консольних застосувань. Проте програмне середовище Visual Studio 2005 містить всі необхідні засоби для створення графічних

Page 11: метуказлабраб ооп 2011укр

11

застосувань Windows. Ви можете проектувати заснований на формі інтерфейс користувача інтерактивно, використовуючи Visual Designer. Visual Studio 2005 тоді згенерує програмний код, що реалізує проектований вами інтерфейс.

З сказаного вище виходить, що Visual Studio 2005 підтримує два представлення застосування: Design View і Code View. Вікно Code and Text Editor може відображати обидва ці уявлення, і ви можете перемикатися на будь-яке з них.

У цій вправі ви навчитеся створювати графічні застосування Windows на C# в Visual Studio 2005.

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

згенерувала Visual Studio 2005, використовуватимете Visual Designer для зміни властивостей елементів управління, використаєте Visual Designer для зміни розмірів форми, напишете код обробника натиснення на кнопку і запустите ваше перше графічне застосування Windows.

1. У меню File виберіть New, а потім Project. Відкриється діалогове вікно New Project.

2. У панелі Project types виберіть Visual C#, Window. У панелі Templates виберіть Windows

Application.

3. Переконайтеся, що поле Location указує на ваш робочий каталог.

4. У полі Name надрукуйте WinFormHello.

5. Переконайтеся, що в полі Solution вибране Create new Solution. Це приведе до створення нового Рішення для підтримки застосування Windows. Як альтернатива можна було вибрати Add to Solution, і тоді новий проект додасться до Рішення TextHello.

6. Клацніть OK. Visual Studio 2005 закриє вікно вашого попереднього застосування, створить і відобразить порожню форму Windows у вікні Design View.

Page 12: метуказлабраб ооп 2011укр

12

Створення призначеного для користувача інтерфейсу.

7. Клацніть закладку Toolbox, яка відображається зліва від форми у вікні Design View. Панель Toolbox розкриється, частково закриваючи форму, і відобразить різні компоненти і елементи управління, які ви можете помістити на форму.

8. У панелі Toolbox клацніть по знаку + поряд з Common Controls щоб відобразити список елементів управління, найчастіше використовуваних застосуваннями Windows.

9. Клацніть Label, а потім клацніть на видимій частині форми. Елемент Label додасться на форму, і панель Toolbox закриється.

10. Елемент Label знаходиться, можливо, не на тому місці, де ви хочете. Ви можете виділити його і перемістити в потрібне місце форми. Перемістіть його в лівий верхній кут форми.

11. У меню View виберіть Properties Window. Вікно Properties з'явиться в правій частині екрану. Вікно Properties дозволяє вам встановлювати властивості елементів проекту. Воно контекстно залежне і відображає властивості виділеного елементу.

12. Виділіть елемент Label на формі. У вікні Properties знайдіть властивість Text, змініть її з label1 на Enter your name і натисніть Enter. На формі текст мітки зміниться на Enter Your

Name.

13. Знову активізуйте панель Toolbox. Клацніть TextBox а потім клацніть на формі. Елемент TextBox додасться на форму. Перемістіть елемент TextBox так, щоб він розташувався під елементом Label.

14. Припускаючи, що елемент TextBox виділений, знайдіть його властивість Text у вікні Properties, наберіть here і натисніть Enter. На формі слово here з'явиться в елементі TextBox.

15. У вікні Properties знайдіть властивість (Name). Visual Studio 2005 дає всім елементам управління і формам імена за умовчанням, які хоч і є хорошою стартовою позицією, але не завжди дуже виразні. Зміните ім'я елементу TextBox на userName.

16. Знову активізуйте панель Toolbox. Клацніть Button а потім клацніть на формі. Перетягніть елемент Button і розташуйте його праворуч від елементу TextBox.

17. Використовуючи вікно Properties, змініть властивість Text кнопки на OK. Змініть її властивість (Name) на ok. Заголовок на кнопці зміниться.

18. Клацніть Form1 form у вікні Design View. На межах форми з'являться маркери зміни розміру.

19. Використовуючи маркери зміни розміру, змініть розмір форми так, щоб вона виглядала приблизно так:

Page 13: метуказлабраб ооп 2011укр

13

20. У Solution Explorer натисніть праву кнопку миші на файлі Form1.cs, а потім клацніть View

Code. Початковий файл Form1.cs з'явиться у вікні Code and Text Editor. Тепер ми маємо дві закладки з ім'ям Form1.cs вище Code and Text Editor/Design View window. Ви можете у будь-який час клацнути на одній з них з суфіксом [Design], щоб повернутися у вікно Design View.

Файл Form1.cs містить код, що автоматично згенерувала Visual Studio 2005. Ви можете відзначити наступні елементи:

• Директиви using

Visual Studio 2005 помістила ряд директив using в початок файлу початкового коду. Наприклад

using System.Windows.Forms;

Це додаткові простори імен (namespaces), що містять класи і елементи управління, які використовуються при розробці графічних застосувань Windows, – наприклад класи TextBox, Label і Button.

• Простір імен

Visual Studio 2005 використала ім'я проекту як ім'я простору імен застосування верхнього рівня.

namespace WinFormHello { ... }

• Клас

Visual Studio 2005 створила клас, названий Form1, в просторі імен WinFormHello

namespace WinFormHello

{

partial class Form1 ...

{

...

}

}

Цей клас представляє форму, спроектовану вами в Design View. Цей клас містить конструктор, який викликає метод InitializeComponent, і нічого більшого. Проте Visual Studio 2005 виконує “спритний трюк” і приховує від нас частину коду, і це можна продемонструвати.

Щоб відобразити прихований код поверніться в Solution Explorer і натисніть кнопку Show All Files. З'являться директорії bin та obj, набагато більші, ніж при розробці консольних застосувань. При цьому зверніть увагу на те, що Form1.cs тепер має знак +. Якщо ви клацнете на цьому плюсі, ви побачите файл з ім'ям Form1.Designer.cs і файл з ім'ям Form1.resx.

Виконайте подвійне клацання на файлі Form1.Designer.cs щоб відобразити його вміст у вікні Code and Text Editor. Ви побачите решту частини коду класу Form1. C# дозволяє вам розбити код для класу на декілька початкових файлів, при цьому кожна частина класу позначається своїм ключовим словом. Цей файл містить регіон, помічений як Windows Form Designer generated code. Розкриття цього регіону клацанням по + показує

Page 14: метуказлабраб ооп 2011укр

14

код, створений і підтримуваний Visual Studio 2005, коли ви редагуєте форму у вікні Design View. Поточний вміст цього файлу включає:

• Метод InitializeComponent

Цей метод згадується у файлі Form1.cs. Оператори усередині цього методу встановлюють властивості елементів управління, які ви додали на форму в Design View. Деякі з операторів цього методу, відповідні діям, виконаним вами у вікні Properties, показані нижче.

... private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.userName = new System.Windows.Forms.TextBox(); this.ok = new System.Windows.Forms.Button(); ... this.label1.Text = "Enter your name"; ... this.userName.Text = "here"; ... this.ok.Text = "OK"; ... } ...

• Три поля

Visual Studio 2005 створила три поля усередині поля Form1. Ці поля можна знайти ближче до кінця файлу:

private System.Windows.Forms.Label label1;

private System.Windows.Forms.TextBox userName;

private System.Windows.Forms.Button ok;

...

Ці поля відповідають трьом елементам управління, які ви додали на форму в Design View.

Варто відзначити, що хоча цей файл (Form1.Designer.cs) цікавий для огляду, ви не повинні ніколи редагувати його вміст безпосередньо. Visual Studio 2005 автоматично модифікує цей файл, коли ви вносите зміни до Design View. Будь-який код, який вам потрібно написати самостійно, повинен бути розміщений у файлі Form1.cs.

Можливо, вас ще цікавить, де знаходиться метод Main, і як відображається форма у момент запуску застосування. Пам'ятаєте, що Main визначає точку входу в програму. У вікні Solution Explorer ви, напевно, відмітили інший файл початкового коду, названий Program.cs. При подвійному клацанні на цьому файлі з'явиться наступний код у вікні Code and Text Editor:

namespace WinFormHello { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.Run(new Form1()); } }

Page 15: метуказлабраб ооп 2011укр

15

}

Ви можете ігнорувати більшу частину цього коду. Проте ключовим оператором тут є оператор

Application.Run(new Form1());

Цей оператор створює форму і показує її, після чого форма починає діяти.

А зараз ми вивчимо, як додати код, який працюватиме при натисненні на кнопку OK на формі.

Написання коду для кнопки OK.

21. Клацніть закладку Form1.cs[Design], розташовану вище за вікно Code and Text Editor, щоб відобразити Form1 в режимі Design View.

22. Помістіть курсор миші над кнопкою OK на формі і виконайте подвійне клацання. У вікні редактора Code and Text Editor завантажиться файл початкового коду Form1.cs. Visual Studio 2005 додала метод ok_Click в клас Form1. (Вона також додала оператора в метод InitializeComponent у файлі Form1.Designer.cs для автоматичного виклику ok_Click коли кнопка OK буде натиснута. Це було зроблено за допомогою делегатів, яких ми вивчатимемо трохи пізніше.)

23. Надрукуйте оператора MessageBox, показаного нижче, усередині методу ok_Click.

Повністю цей метод виглядатиме так:

private void ok_Click(object sender, System.EventArgs e) { MessageBox.Show("Hello " + userName.Text); }

Зараз ви готові до запуску вашого графічного застосування Windows.

24. Запуск застосування. У меню Debug виберіть пункт Start Without Debugging. Visual Studio 2005 збереже вашу роботу, відтранслює програму і запустить її.

Методичні вказівки і теоретичні відомості.

Що таке .NET Framework

.NET Framework – це платформа розробки для створення застосувань, які легко розгортаються і виконуються на різних апаратних платформах і різних операційних системах. Ця портованість досягається за рахунок стандартизації, що продовжується, в організаціях ECMA і ISO. Таким чином .NET Framework пропонує незалежність від мови програмування, поставляючи міжнародний стандарт, званий Common Language Infrastructure (CLI). Мова програмування, сумісна з цією платформою, повинна дотримуватися стандарту, визначеного в Common Language

Specification (CLS).

Зараз .NET Framework інсталюється поверх операційної системи (поточна версія – .NET Framework 2.0), а в майбутній операційній системі Windows Vista ця платформа підтримуватиметься на рівні операційної системи. .NET Framework складають два шари, як показано на малюнку 1: загальномовне середовище виконання (Common Language Runtime – CLR), схоже на віртуальну машину Java, і велика бібліотека класів, звана Framework Class

Library (FCL), яка надає сервіси застосуванням.

Page 16: метуказлабраб ооп 2011укр

16

Мал. 1. Огляд .NET Framework

Загальномовне середовище виконання

Загальномовне середовище виконання .NET — нове могутнє середовище розробки від Microsoft, що забезпечує унікальні можливості по міжпрограмній і міжплатформеній інтеграції програмних засобів. Для її реалізації була розроблена єдина концепція використання керованого коду. Ми розглянемо основні принципи побудови платформи .NET, внутрішній устрій середовища виконання, загальні принципи роботи віртуальних машин, а також природу і устрій керованого коду. Ви дізнаєтеся, для чого створювалося середовище виконання, і які задачі воно здатне вирішити [5].

Архітектура середовища виконання .NET

Загальномовне середовище виконання (Common Language Runtime, CLR) — це загальне незалежне віртуальне програмне середовище для застосувань, що забезпечує ефективне і контрольоване виконання призначеного для користувача коду, а також що надає розробникам програмних систем широкий спектр різноманітних сервісів. Воно істотно полегшує розробку сучасних застосувань, поєднуючи в собі багато переваг технології RAD (Rapid Application Development, Швидка Розробка Застосувань), з високою продуктивністю і швидкістю роботи кінцевих застосувань. Структурно загальномовне середовище виконання .NET складається з двох компонентів: віртуальної машини і загальної бібліотеки класів.

Віртуальна машина відповідає за виконання коду, а загальна бібліотека класів надає розробникам чітко стандартизований набір типів. Початкова мова програмування, на якій написано застосування для середовища .NET, не має значення; від транслятора мови лише потрібне уміння генерувати "керований" код, який розуміє віртуальна машина .NET. Такий код працює тільки в середовищі CLR, що забезпечує повний контроль над всіма процесами при виконанні застосування.

Керований код — нове поняття, введене розробниками Microsoft, яке спочатку викликає утруднення для розуміння у більшості програмістів [5]. Його особливістю є те, що він виконується під постійним наглядом середовища виконання, яке контролює всі його кроки. Саме із-за такого сильного контролю і нагляду було вирішено назвати код керованим. Він представляється в спеціальному форматі, званому .NET байт-код. Для візуального представлення внутрішнього .NET байт-коду розроблена мова IL (Intermediate Language, Проміжна Мова Microsoft). По суті справи, вона знаходиться на одному рівні з .NET байт-кодом, але це не сам байт-код, а лише його текстове представлення. Для порівняння можна сказати, що IL і .NET байт-код співвідносяться, як асемблер і машинний код. Таким чином, всі застосування поставляються для виконання на віртуальній машині .NET у вигляді уніфікованого .NET байт-коду.

Для створення низькорівневого байт-коду з високорівневої мови, використовуються відповідні компілятори. Створювати застосування .NET можливо більш ніж на десяти різних мовах програмування високого рівня [5]. При цьому загальні стандарти середовища виконання .NET, в особі загальномовної специфікації CLS (Common Language Specification) і загальної системи типів CTS (Common Type System), гарантуватимуть інтеграцію коду незалежно від початкової мови, використаної для створення застосування.

Page 17: метуказлабраб ооп 2011укр

17

Інтеграція коду має на увазі повну сумісність коду на всіх рівнях: починаючи від стандартів визначення типів і закінчуючи моделлю підтримки асинхронних подій. Наприклад, ви можете визначити клас за допомогою мови С#, а успадкувати його, використовуючи Visual Basic .NET (VB .NET). Особливістю системи .NET є використання оригінальної технології інтеграції коду, яка забезпечує сумісність коду не на рівні виконуючого ядра (процесора, віртуальної машини .NET), а на рівні самої програмної моделі. Раніше, коли створювався код для процесорів з використанням ортодоксальних компіляторів, основним завданням програмістів було забезпечення лише односторонньої сумісності з самим процесором, розробники якого вводили власні стандарти на машинний код, практично не думаючи про користувачів мов високого рівня. В результаті, сформований машинний код представляв всього лише послідовний набір команд для процесора, який наказував йому зробити певні дії.

NET байт-код є не просто набором команд для віртуальної машини .NET. Він якісно відрізняється від машинного коду наявністю повного опису внутрішньої структури програми, починаючи від локальної змінної і закінчуючи класами і просторами імен. Фактично, при класичній компіляції в машинний код повністю втрачається інформація про внутрішній устрій програми, яка за великим рахунком і не потрібна для її виконання. Зате така інформація життєво необхідна при рішенні задач міжмовної і міжпрограмної інтеграції. При компіляції в керований .NET байт-код втрат цієї інформації не відбувається і повне уявлення про внутрішню організацію програми зберігається в спеціальних структурах, званих метаданими. Таким чином, технологія керованого байт-коду дає величезні переваги у вигляді міжмовної інтеграції і крос-платформовій переносимості коду. Але всі переваги підходу можуть бути зведені до мінімуму низькими показниками продуктивності із-за повної віртуалізації виконання байт-коду. Практичним підтвердженням тому можуть служити Java (класична машина від Sun) і Microsoft Visual Basic .NET (ранніх версій) [5]. Продуктивність при виконанні коду обох систем залишає бажати багато кращого.

Існує два види віртуальних машин — що інтерпретують і компілюють. Інтерпретуючі машини виконують код, повністю емулюючи його роботу. Фактично, вони самі виконують код увірених їм застосувань. Тобто на кожну інструкцію байт-коду, що інтерпретується, доводиться N інструкцій інтерпретатора віртуальної машини. У результаті, відбувається значне зниження швидкості виконання програми. За що і не люблять віртуальні машини такого типу.

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

Для реалізації подібного підходу у віртуальній машині потрібна наявність дуже важливого компоненту – компілятора часу виконання JIT (Just-In-Time Compiler), який забезпечує трансляцію .NET байт-коду в машинний прямо по ходу виконання програми. Такі компілятори зазвичай називають двійковими. По всіх тестах на продуктивність, проведених для платформи .NET, вона практично ні в чому не поступається класичним компілюючим системам, а по деяких – навіть перевершує їх. З докладними звітами цих тестів можна ознайомитися на сайті http://www. rsdn.ru [5].

Середовище виконання .NET може базуватися на різних апаратних (Intel, Pocket РС) і програмних платформах (Windows, FreeBSD, MacOS, Linux). Для кожної підтримуваної апаратної і програмної платформи повинна існувати власна реалізація подібного компілятора і для кожної нової апаратної платформи розробникам доведеться створювати власний ЛТ-компілятор, який переводитиме

Page 18: метуказлабраб ооп 2011укр

18

універсальний незалежний .NET байт-код в конкретний машинний код. У цьому полягає, мабуть, основний недолік цієї технології [5].

У загальному вигляді внутрішній устрій віртуальної машини .NET можна представити таким чином (мал. 2).

Мал. 2. Загальна схема віртуальної виконуючої машини .NET

Загальна бібліотека класів

Загальна бібліотека класів .NET від Microsoft (Framework Class Library, FCL) могутня і різноманітна і надає користувачеві величезний спектр сервісів. Перерахувати їх повністю не представляється можливим, приведемо лише деякі з них (Таблиця 1) [5]. Число класів бібліотеки FCL велике (декілька тисяч). Тому знадобився спосіб їх структуризації. Логічно класи з близькою функціональністю об'єднуються в групи, звані простором імен (Namespace).

Основним простором імен бібліотеки FCL є простір System, що містить як класи, так і інші вкладені простори імен. Так, примітивний тип int безпосередньо вкладений в простір імен System і його повне ім'я, що включає ім'я простору, - System.Int32.

У простір System вкладений цілий ряд інших просторів імен. Наприклад, в просторі System.Collections знаходяться класи і інтерфейси, що підтримують роботу з колекціями об'єктів - списками, чергами, словниками. У простір System.Collections, у свою чергу, вкладений простір імен Specialized, що містять класи із спеціалізацією, наприклад, колекції, елементами яких є тільки рядки. Простір System.Windows.Forms містить класи, використовувані при створенні Windows-застосувань. Клас Form з цього простору задає форму – вікно, що заповнюється елементами управління, графікою, забезпечує інтерактивну взаємодію з користувачем [30].

Таблиця 1. Набір основних сервісів, що надаються через загальну бібліотеку класів

Простір імен Сервіси класу System Базові типи, використовувані всіма застосуваннями.

System.Collections Колекції для зберігання наборів об'єктів System.Drawing Сервіси для роботи з двовимірною графікою

System.IO Підтримка потокового введення виведення, у тому числі і файлового

System.Net Підтримка мережевої взаємодії System.Resources Сервіси для роботи з ресурсами

Page 19: метуказлабраб ооп 2011укр

19

System.Security Сервіси підтримки захисту і безпеки

System.Text Сервіси для роботи з текстом System.Threading Сервіси підтримки багатопотокового коду

System.Xml Сервіси для роботи з даними у форматі XML System.Web.Services Засоби, призначені для створення Web-сервісів XML

System.Web.UI Сервіси для зручного створення Web-призначених для користувача інтерфейсів (Web Forms)

System.Windows.Forms Сервіси підтримки класичних призначених для користувача інтерфейсів

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

Типи даних C#

У мові C# існує два різновиди типів даних: значущі типи (value types) і посилальні типи (reference types). До значущих типів відносяться прості типи (char, int, float), перераховувані типи (enum) і структури (struct), тобто типи, що безпосередньо містять дані. Це переважно локальні змінні і параметри методів, які поміщаються в стек потоку. Якщо потрібно скористатися посиланням на подібні дані, доводиться використовувати операцію boxing (обгортання або упаковка).

Посилальними типами є класи, інтерфейси, масиви (підтримуються одно- і багатовимірні масиви) і делегати: типи, що зберігають посилання на методи. Для доступу до екземплярів подібних типів використовуються посилання, які указують на реальні об'єкти, розташовані в динамічній пам'яті застосування.

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

Важливою частиною бібліотеки FCL стали класи, що задають примітивні типи - ті типи, які вважаються вбудованими в мову програмування. Типи .NET Framework покривають всю множину вбудованих типів, що зустрічаються в мовах програмування. Типи мови програмування проектуються на відповідні типи .NET Framework. Тип, званий в мові Visual Basic, - Integer, а в мові C# - int, проектується на один і той же тип System.Int32. У кожній мові програмування, разом з "рідними" для мови назвами типів, дозволяється користуватися іменами типів, прийнятими в .NET Framework. Тому, по суті, всі мови середовища розробки можуть користуватися єдиною системою вбудованих типів, що, звичайно, сприяє полегшенню взаємодії компонентів, написаних на різних мовах

Зумовлені типи даних

Мова C# містить ряд вбудованих (built-in) зумовлених значущих і посилальних типів, більшість з яких прийшла з мов С/С++. Іноді їх називають примітивними типами даних.

До зумовлених значущих типів відносяться цілочисельні типи (із знаком — sbyte, short, int, long і без знаку — byte, ushort, uint, ulong), числа з плаваючою крапкою (float і double) і типи bool, char і decimal. Таблиця 2 містить опис найбільш часто використовуваних примітивних типів даних.

Page 20: метуказлабраб ооп 2011укр

20

Таблиця 2. Примітивні типи даних мови C#.

Тип Опис Розмір

(битий)

Діапазон Приклад

int цілі числа 32 <–>231 through 231<–>1 int count; count = 42;

long цілі числа (більший діапазон) 64 <–>263 through 263<–>1 long wait; wait = 42L;

float числа з плаваючою крапкою 32 ±3.4 × 1038 float away;

away = 0.42F; double числа з плаваючою точкою

подвійної точності 64 ±1.7 × 10308 double trouble;

trouble = 0.42; decimal грошовий тип 128 28 значущих цифр decimal coin;

coin = 0.42M; string послідовність символів 16 битий на

символ не застосуємо string vest;

vest = "42"; char одиночний символ 16 0 through 216 <–>1 char grill;

grill = '4'; bool булевий тип 8 true або false bool teeth;

teeth = false; *Значення 216 є 32,768; Значення 231 є 2,147,483,648; і Значення 263 є 9,223,372,036,854,775,808.

Зумовлені посилальні типи представлені типами object і string. Тип object є універсальним базовим типом для решти всіх типів.

Введення даних користувачем і їх виведення

Розглянемо наступний фрагмент програми [2]:

static void Main(srting[] args ) {

double firstNumber, secondNumber;

string username;

Console.WriteLine(“Enter your name:”);

username = Console.ReadLine();

Console.WriteLine(“Welcome {0}!”, userName);

Console.WriteLine(“Now give me а number:”);

firstNumber = Convert.ToDouble(Console.ReadLine());

Console.WriteLine(“Now give me another number:”);

secondNumber = Convert.ToDouble(Console.ReadLine());

Console.WriteLine(“The sum of {0} and {1} is {2}.”, firstNumber, secondNumber, firstNumber + secondNumber); }

Як це працює. Для введення даних, здійснюваного користувачем, застосовується синтаксис, аналогічний синтаксису команди Console.WriteLine(). В даному випадку використовується команда Console.ReadLine(), яка генерує рядок. При прочитуванні двох дійсних чисел необхідно виконати перетворення типів за допомогою Convert.ToDouble().

Після цього виводяться числа і результат додавання. Усередині дужок функції Console.WriteLine(. . .)є два елементи: рядок формату і список змінних, розділених комами. Кожен комплект фігурних дужок в цьому рядку є зарезервованим місцем, в якому розміщуватиметься вміст чергової змінної із списку. Кожне таке зарезервоване місце має вид цілого числа у фігурних дужках. Ці цілі числа мають значення, що починаються з 0 і збільшуються на 1, а сумарна кількість таких місць повинна відповідати загальному числу змінних.

Page 21: метуказлабраб ооп 2011укр

21

Вказівки до завдання 3.

Елементам управління рекомендується дати такі імена: lhsOperand, rhsOperand, expression, result – для полів типа TextBox; remainder, division, multiplication, subtraction, addition – для елементів типа RadioButton; quit, calculate – для кнопок Button.

Для обчислень корисно ввести методи, подібні такому:

private void subtractValues()

{

int lhs = int.Parse(lhsOperand.Text);

int rhs = int.Parse(rhsOperand.Text);

int outcome;

outcome = lhs – rhs;

expression.Text = lhsOperand.Text + " – " + rhsOperand.Text;

result.Text = outcome.ToString();

}

Тут значення, що вводяться користувачем, перетворяться до цілого типу за допомогою методу int.Parse().

Вказівки до завдання 4.

На форму треба помістити два елементи управління типа DateTimePicker, назвавши їх first і second. (Ці елементи управління відображають календар, в якому можна вибрати дату.) У початковий момент ці елементи управління повинні відображати поточну дату.

Обробник натиснення на кнопку Compare може мати приблизно такий вигляд:

private int compare_Click(object sender, System.EventArgs e)

{

int diff = dateCompare(first.Value, second.Value);

info.Text = "";

show("first == second", diff == 0);

show("first != second", diff != 0);

show("first < second", diff < 0);

show("first <= second", diff <= 0);

show("first > second", diff > 0);

show("first >= second", diff >= 0);

}

Тепер залишилося написати методи dateCompare і show. Структура методу dateCompare може бути така:

private int dateCompare(DateTime leftHandSide, DateTime rightHandSide)

{

// TO DO

return . . .;

}

Параметри типа DateTime мають властивості Year, Month, Day. Їх треба використовувати в методі dateCompare.

Метод show показує результати порівняння в полі info типа TextBox.

Page 22: метуказлабраб ооп 2011укр

22

Приклади [29] Приклад #1: Прості типи даних

class TestMain

{ public static void Main( ) // Code Starts Here { bool b=true; System.Console.WriteLine(b); // boolean byte by=200; System.Console.WriteLine(by); // byte sbyte sby=-100; System.Console.WriteLine(sby); // signed byte decimal dec=10m; System.Console.WriteLine(dec);//decimal(28-29 signif) double dbl=12.2e23; System.Console.WriteLine(dbl); // double prec. float fl=12.2f; System.Console.WriteLine(fl); // single prec. char c='A'; System.Console.WriteLine(c); // unicode character short sh=10; System.Console.WriteLine(sh); // signed 16 bit ushort ush=10; System.Console.WriteLine(ush); // unsigned 16 bit int i=10; System.Console.WriteLine(i); // signed 32 bit uint ui=10; System.Console.WriteLine(ui); // unsigned 32 bit long l=10; System.Console.WriteLine(l); // signed 64 bit ulong ul=10; System.Console.WriteLine(ul); // unsigned 64 bit } }

Приклад #2: Приведення типів

class TestMain { public static void Main( ) // Code Starts Here { int x; x='A'; // implicit cast (неявне приведення) x= (int) 34.34F; // explicit cast (явне приведення) decimal dec=x; // implicit cast dec = (decimal)6.673e-11 ; //explicit cast dec=12+'A'; // implicit cast System.Console.WriteLine(dec); } }

Приклад #3: Функції

using System; class TestMain { private static int Sum(int x,int у) int total; total=x+y; return total; } private static void Sum(int x,int у,out int total) // out modifier { total=x+y; }

private static void Sum(int x,int у,ref int total) // by ref { Console.WriteLine("Total = "+total); total=x+y; } public static void Main( )

Page 23: метуказлабраб ооп 2011укр

23

{ Console.WriteLine("Sum="+Sum(10,20)); int ans; Sum(20,30,out ans); // Must call with out Console.WriteLine("Sum="+ans); ans=123; Sum(30,40,ref ans); // Must Call with ref Console.WriteLine("Sum="+ans); } }

Приклад #4: Призначене для користувача введення

using System; class TestMain { public static void Main( ) { Console.Write("Enter A Line: "); String line=Console.ReadLine(); Console.WriteLine("You Entered: "+line); } }

Приклад #5: Операція ==

using System; class Disk { private String mName; public Disk(String name) { mName=name; } String GetName() { return mName; } } class TestMain { public static void Main( ) { Disk x=new Disk("One"); Disk y=new Disk("Two"); if(x==y) // Check if x references same object as у Console.WriteLine("x+y reference same object"); } x=y; if(x==y) // Check if x references same object as у Console.WriteLine("Now x+y reference same object"); } // In Strings the == operator is overloaded to compare the values of strings Console.Write("Enter а string:");

String str1=Console.ReadLine(); // Read а string in Console.Write("Enter а string:");

String str2=Console.ReadLine(); // Read а string in if(str1==str2) Console.WriteLine("Both strings are the same"); } else Console.WriteLine("Strings are different"); } } }

Page 24: метуказлабраб ооп 2011укр

24

Приклад #6: Перетворення типа String в будь-який простий тип

using System; class TestMain { public static void Main( ) { String one="111111"; int i=Convert.ToInt32(one); // Conversions may throw exceptions double db=Convert.ToDouble(one); decimal dec=Convert.ToDecimal(one); } }

Приклад #7: Структури

using System; struct Point { public int x,y; } class TestMain { public static void Main( ) Point pt; pt.x=10; pt.y=20; } }

Приклад #8: Перерахування

using System; enum Colors { BLUE=0xFF0000,GREEN=0x00FF00,RED=0x0000FF} class TestMain { static void Main() { Console.WriteLine("Data: "+Colors.BLUE); Colors x=Colors.GREEN; Console.WriteLine("Data: "+x); } }

Приклад #9: Форматоване виведення

using System; class TestMain { private static void Main() { Console.WriteLine("{0}={1}+{2}",23,20,3); Console.WriteLine("{0} {1} {1} {1} {2} {2} {2}","Hello",123,45.5); Console.WriteLine("{0}""); // format specifier Console.WriteLine("{0:c}",123); // Print in Currency Console.WriteLine("{0:x}",2222321); // print in hexidecimal Console.WriteLine("{0:f}",1.2343); // print as float // Total Space

Page 25: метуказлабраб ооп 2011укр

25

Console.WriteLine("-->{0,10}<--",800); // 10 spaces on right Console.WriteLine("-->{0-10}<--",800); // 10 spaces on left Console.WriteLine("-->{0,10}<--",1234.5); Console.WriteLine("-->{0-10}<--",1234.5); // Total Space+format specifier Console.WriteLine("-->{0,10:f}<--",56); Console.WriteLine("-->{0,10:x}<--",56); Console.WriteLine("-->{0-10:x}<--",561); // Extra modifers

Console.WriteLine("-->{0:f4}<--",1.23); // 4 spaces after decimal Console.WriteLine("-->{0:x6}<--",1234);//Print 6 spaces + pad with zero Console.WriteLine("-->{0:c2}<--",1234.2323); // print 2 spaces after zero

// What is the output? Console.WriteLine("-->{0,10:f4}<--",123); Console.WriteLine("-->{0-10:f4}<--",123); Console.WriteLine("-->{0,20:c2}<--",1231121); Console.WriteLine("-->{0-20:c2}<--",12321212); } }

Лабораторна робота №2. Цикли, рядки, файли в C#.

Мета роботи: засвоїти основні управляючі конструкції мови C#, набути практичних навичок роботи з рядками і файлами.

Завдання.

1. Розробити консольний і графічний варіант простого переглядача текстових файлів. Використовувати елементи управління Button, Label, TextBox, OpenFileDialog і оператор циклу while. Зразок вигляду головного вікна програми в графічному варіанті:

Page 26: метуказлабраб ооп 2011укр

26

2. Розробити програму, що демонструє кроки перетворення цілого числа в рядок з використанням циклу do . . . while. Зразковий вид головного вікна програми.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати завдання 1-2.

Вправа 1. Використання класу FileStream для читання з файлу з довільним доступом

Наступний приклад демонструє прочитування даних з файлу з довільним доступом. Як файл, з якого проводитиметься читання, використовується файл .cs самого застосування.

1. Відкрийте Visual Studio 2005 і створіть нове C# Console Application, назвавши його ReadFile.

2. Додайте два наступні оголошення просторів імен в самий початок файлу Class1.cs. Простір імен System.IO необхідний для класу FileStream, а простір імен System.Text буде потрібний для здійснення перетворення, яке нам доведеться виконувати над байтами, що прочитуються з файлу.

using System; using System.IO; using System.Text;

3. Додайте наступний код в метод Main():

static void Main(string[] args) { byte[] byData = new byte[100]; char[] charData = new char[100]; try { FileStream aFile = new FileStream(“../../Class1.cs”,FileMode.Open); aFile.Seek(55, SeekOrigin.Begin); aFile.Read(byData, 0, 100); } catch(IOException e) { Console.WriteLine(“An IO exception has been thrown!”);

Page 27: метуказлабраб ооп 2011укр

27

Console.WriteLine(e.ToString()); Console.ReadLine(); return; } Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); Console.WriteLine(charData); Console.ReadLine(); return; }

4. Запустіть застосування.

Вправа 2. Відрядкове читання з файлу за допомогою класу StreamReader

1. Відкрийте Visual Studio 2005 і створіть нове C# Console Application, назвавши його StreamRead.

2. Додайте оголошення простору імен System.IO.

3. Додайте наступний код в метод Main():

static void Main(string[] args) { string strLine; try { FileStream aFile = new FileStream(“Log.txt”,FileMode.Open); StreamReader sr = new StreamReader(aFile); strLine = sr.ReadLine(); //Відрядкове прочитування даних while(strLine != null) { Console.WriteLine(strLine); strLine = sr.ReadLine(); } sr.Close(); Console.ReadLine(); } catch(IOException e) { Console.WriteLine(“An IO exception has been thrown!”); Console.WriteLine(e.ToString()); Console.ReadLine(); return;

} return; }

4. Створіть в директорії StreamRead\bin\Debug файл Log.txt.

5. Запустіть застосування.

Методичні вказівки та теоретичні відомості.

Цикли

Щоб багато разів виконати послідовність програмних інструкцій, необхідно організувати цикл. У мові C# циклічні конструкції представлені в багатому асортименті.

Page 28: метуказлабраб ооп 2011укр

28

Цикл for

Загальний формат запису циклу for для повторного виконання однієї інструкції має наступний вигляд:

for(ініціалізація; умова; ітерація)Інструкція;

Якщо цикл for призначений для повторного виконання програмного блоку, то його загальний формат виглядає так:

for(ініціалізація; умова; ітерація) { Послідовність інструкцій }

Елемент ініціалізація зазвичай є інструкцією привласнення, яка встановлює початкове значення змінній циклу. Ця змінна діє як лічильник, який управляє роботою циклу. Елемент умова є вираз типу bool, в якому тестується значення змінної циклу. Результат цього тестування визначає, виконається цикл for ще раз чи ні. Елемент ітерація – це вираз, який визначає, як змінюється значення змінної циклу після кожної ітерації. Зверніть увагу на те, що всі ці елементи циклу for повинні відділятися крапкою з комою. Цикл for виконуватиметься до тих пір, поки обчислення елементу умова дає дійсний результат. Як тільки умова стане помилковою, виконання програми продовжиться з інструкції, наступної за циклом for.

Приклад.

class TestMain

{ public static void Main( ) { for(int i=0;i<10;++i) { if(i==5) { continue; }// continue

if(i>8) { break; }// break

System.Console.WriteLine(i);

} } }

Цикл while

Загальна форма циклу while має такий вигляд:

while (умова) інструкція;

Тут під елементом інструкція розуміється або одиночна інструкція, або блок інструкцій. Роботою циклу управляє елемент умова, який є допустимим виразом типу bool. Елемент інструкція виконується до тих пір, поки умовний вираз повертає значення true. Як тільки ця умова стане помилковою, управління передається інструкції, яка слідує за цим циклом.

Приклад. class TestMain { public static void Main( ) int i; i=0; while(i<10) { i=i+1; if(i==5) { continue; } if(i>8) { break; }

System.Console.WriteLine(i);

Page 29: метуказлабраб ооп 2011укр

29

} } }

Цикл do-while

Третім циклом в C# є цикл do-while. На відміну від циклів for і while, в яких умова перевіряється при вході, цикл do-while перевіряє умова при виході з циклу. Це означає, що цикл do-while завжди виконується хоч би один раз. Його загальний формат має такий вигляд:

do { інструкції; } while (умова);

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

using System;

class DoWhileDemo {

public static void Main() {

int num; int nextdigit;

num = 198;

Console.WriteLine(“Число: ” + num);

Console.WriteLine(“Число із зворотним порядком цифр: ”);

do { nextdigit = num % 10; Console.Write(nextdigit); num = num / 10; } while(num > 0);

Console.WriteLine(); } }

Цикл foreach

Цикл foreach використовується для опиту елементів колекції. Колекція – це група об'єктів. C# визначає декілька типів колекцій, і одним з них є масив. Формат запису циклу foreach має такий вигляд:

foreach (тип ім’я_змінної in колекція) інструкція;

Тут елементи тип і ім’я_змінної задають тип і ім'я ітераційної змінної, яка при функціонуванні циклу foreach набуватиме значень елементів з колекції.

Приклад.

using System; public class ForEachLoop { public static int Main(string[] args) { int [] primes = {2, 3, 5, 7, 11, 13}; int sum = 0; foreach (int prime in primes) { Console.Write("{0} ", prime); sum += prime; } Console.WriteLine(); Console.WriteLine("sum = {0}", sum); return 0; }

Page 30: метуказлабраб ооп 2011укр

30

}

Робота з рядками і символами

Клас Char

У C# є символьний тип char, заснований на класі System.Char і що використовує двобайтове кодування Unicode представлення символів. Для цього типу в мові визначені символьні константи - символьні літерали. Константу можна задавати:

• символом в одинарних лапках; • escape-послідовністю, що задає код символу; • Unicode-послідовністю, що задає Unicode-код символу.

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

public void TestChar() { char ch1='A', ch2 ='\x5A', ch3='\u0058'; char ch = new Char(); int code; string s; ch = ch1; //перетворення символьного типу в тип int code = ch; ch1=(char) (code +1); //перетворення символьного типу в рядок //s = ch; s = ch1.ToString()+ch2.ToString()+ch3.ToString(); Console.WriteLine("s= {0}, ch= {1}, code = {2}", s, ch, code); }//TestChar

Клас Char, як і всі класи в C#, успадковує властивості і методи батьківського класу Object. Але у нього є і власні методи і властивості, і їх немало. Зведення цих методів приведене в таблиці 3.

Таблиця 3. Методи класу Char

Метод Опис

GetNumericValue Повертає чисельне значення символу, якщо він є цифрою, і (-1) інакше

GetUnicodeCategory Всі символи розділені на категорії. Метод повертає Unicode категорію символу.

IsControl Повертає true, якщо символ є таким, що управляє

IsDigit Повертає true, якщо символ є десятковою цифрою

IsLetter Повертає true, якщо символ є буквою

IsLetterOrDigit Повертає true, якщо символ є буквою або цифрою

IsLower Повертає true, якщо символ заданий в нижньому регістрі

IsNumber Повертає true, якщо символ є числом (десятковою або шістнадцятковою цифрою)

IsPunctuation Повертає true, якщо символ є розділовим знаком

IsSeparator Повертає true, якщо символ є роздільником

IsSurrogate Деякі символи Unicode з кодом в інтервалі [0x1000, 0x10FFF] представляються двома 16-бітовими "сурогатними" символами. Метод повертає true, якщо символ є сурогатним

IsUpper Повертає true, якщо символ заданий у верхньому регістрі

IsWhiteSpace Повертає true, якщо символ є "білим пропуском". До білих пропусків, крім пропуску, відносяться і інші символи, наприклад, символ кінця рядка і символ переведення каретки

Page 31: метуказлабраб ооп 2011укр

31

Parse Перетворить рядок в символ. Природно, рядок повинен складатися з одного символу, інакше виникне помилка

ToLower Приводить символ до нижнього регістра

ToUpper Приводить символ до верхнього регістра

MaxValue, MinValue Властивості, що повертають символи з максимальним і мінімальним кодом. Символи, що повертаються, не мають видимого образу

Клас String

Тип даних string (рядки Unicode) – це вбудований тип даних C#. Всі рядки в C# і .NET походять від єдиного базового класу System.String. Цей базовий клас забезпечує ряд методів, які покликані виконати за вас всю чорнову роботу: повернути кількість символів в рядку, знайти підрядки, перетворити всі символи в рядкові або прописні і т.д. Найбільш використовувані члени класу System.String представлені в таблиці 4.

Таблиця 4. Деякі члени класу System.String.

Ім'я члена класу Призначення

Length Ця властивість повертає довжину вказаного рядка

Concat() Цей статичний метод класу String повертає новий рядок, «склеєний» з двох даних рядків

CompareTo() Порівнює два рядки

Copy() Цей статичний метод створює нову копію існуючого рядка

Format() Використовується для форматування рядка

Insert() Використовується для вставки рядка всередину рядка

PadLeft() PadRight() Дозволяють наповнити («набити») рядок вказаними символами

Remove() Replace() Дозволяють створити копію рядка з внесеними змінами

int IndexOf(string str) Виконує в рядку пошук підрядка, заданого параметром str. Повертає індекс першого входження шуканого підрядка або -1, якщо підрядок не буде виявлений

string Substring(int start, int len)

Повертає рядок, який містить задану частину рядка

ToUpper() ToLower() Для отримання копії рядка, в якому всі символи стануть рядковими або прописними

Постійність рядків

Наступне твердження, ймовірно, вас здивує: вміст string-об'єктів незмінний. Іншими словами, послідовність символів, складових рядка, змінити не можна. Так, всі методи, перераховані в таблиці 2, повертають новий рядок з необхідними змінами.

Приклад.

using System;

class SubStr { public static void Main() { string orgstr = “C# спрощує роботу з рядками.”; //Створення підрядка. string substr = orgstr.Substring(3,16); Console.WriteLine(“orgstr: “ + orgstr); Console.WriteLine(“substr: “ + substr); } }

А ось як виглядають результати роботи цієї програми:

Page 32: метуказлабраб ооп 2011укр

32

orgstr: C# спрощує роботу з рядками. substr: спрощує роботу

Клас StringBuilder - будівник рядків

Клас string не дозволяє змінювати існуючі об'єкти. Рядковий клас StringBuilder дозволяє компенсувати цей недолік. Цей клас належить до змінних класів і його можна знайти в просторі імен System.Text. Розглянемо клас StringBuilder докладніше.

Оголошення рядків. Конструктори класу StringBuilder

Об'єкти цього класу оголошуються з явним викликом конструктора класу. Конструктор класу перевантажений, і разом з конструктором без параметрів, що створює порожній рядок, складає набір конструкторів, яким можна передати дві групи параметрів. Перша група дозволяє задати рядок або підрядок, значенням якого ініціалізується створюваний об'єкт класу StringBuilder. Друга група параметрів дозволяє задати місткість об'єкту - об'єм пам'яті, що відводиться даному екземпляру класу StringBuilder. Кожна з цих груп не є обов'язковою і може бути опущена. Прикладом може служити конструктор без параметрів, який створює об'єкт, що ініціалізований порожнім рядком, і з деякою місткістю, заданою за умовчанням, значення якої залежить від реалізації. Приведемо як приклад синтаксис трьох конструкторів: public StringBuilder (string str, int cap). Параметр str задає рядок ініціалізації, cap - місткість об'єкту;

public StringBuilder (int curcap, int maxcap). Параметри curcap і maxcap задають початкову і максимальну місткість об'єкту;

public StringBuilder (string str, int start, int len, int cap). Параметри str, start, len задають рядок ініціалізації, cap - місткість об'єкту.

Операції над рядками

Над рядками цього класу визначені практично ті ж операції з тією ж семантикою, що і над рядками класу String: привласнення (=); дві операції перевірки еквівалентності (= =) і (!=); узяття індексу ([]). Операція конкатенації (+) не визначена над рядками класу StringBuilder, її роль грає метод Append, що дописує новий рядок в хвіст що вже існує.

З рядком цього класу можна працювати як з масивом, але, на відміну від класу String, тут вже все робиться як треба: допускається не тільки читання окремого символу, але і його зміна. Розглянемо приклад: public void TestStringBuilder() { //Рядки класу StringBuilder //операції над рядками StringBuilder s1 =new StringBuilder("ABC") s2 =new StringBuilder("CDE"); StringBuilder s3 = new StringBuilder(); //s3= s1+s2; s3= s1.Append(s2); bool b1 = (s1==s3); char ch1 = s1[0], ch2=s2[0]; Console.WriteLine("s1={0}, s2={1}, b1={2}" + "ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); s2 = s1; b1 = (s1!=s2); ch2 = s2[0]; Console.WriteLine("s1={0}, s2={1}, b1={2}" + "ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); StringBuilder s = new StringBuilder("Zenon"); s[0]='L'; Console.WriteLine(s);

Page 33: метуказлабраб ооп 2011укр

33

}//TestStringBuilder

Цей приклад демонструє можливість виконання над рядками класу StringBuilder тих же операцій, що і над рядками класу String. В результаті привласнення створюється додаткове посилання на об'єкт, операції перевірки на еквівалентність працюють із значеннями рядків, а не з посиланнями на них. Конкатенацію можна замінити викликом методу Append. З'являється нова можливість - змінювати окремі символи рядка. (Для того, щоб ім'я класу StringBuilder стало доступним, в проект додана пропозиція using System.Text, що посилається на відповідний простір імен.)

Робота з файлами

Будь-яке введення і виведення інформації в .NET Framework включає використання потоків – абстрактних представлень послідовних пристроїв.

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

• File – широко використовуваний на практиці клас, який володіє великою кількістю статичних методів, що дозволяють переносити, копіювати і видаляти файли.

• Directory – клас, який володіє великою кількістю статичних методів, що дозволяють переносити, копіювати і видаляти директорії.

• Path – клас, що дозволяє виконувати маніпуляції над іменами шляхів.

• FileInfo – представляє фізичний файл, розташований на диску, і володіє методами, що дозволяють виконувати маніпуляції над цим файлом. Для будь-яких операцій читання/запису, що виконуються над файлом, необхідно створити об'єкт Stream.

• DirectoryInfo – представляє фізичну директорію, розташовану на диску, і володіє методами, що дозволяють виконувати маніпуляції над цією директорією.

• FileStream – представляє файл, який допускає або прочитування, або запис, або і те і інше одночасне. Цей файл може прочитуватися як синхронно, так і асихронно.

• StreamReader – прочитує символьну інформацію з потоку і може створюватися на базі класу FileStream.

• StreamWriter – записує символьну інформацію в потік і може створюватися на базі класу FileStream.

Класи File і Directory

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

Клас FileInfo

На відміну від класу File, клас FileInfo не володіє статичними методами і може використовуватися тільки за допомогою створення екземплярів об'єктів. Об'єкт FileInfo представляє файл, розташований на диску або за деякою мережевою адресою. Відмітьте, що цей клас не є потоком. Для того, щоб здійснити запис у файл або читання з файлу, необхідно створити об'єкт Stream. Об'єкт FileInfo дозволяє вирішити цю задачу, надаючи декілька методів, які повертають створені екземпляри об'єктів Stream. Проте, перш за все, для того, щоб створити об'єкт FileInfo, необхідно вказати шлях до файлу або директорії:

FileInfo aFile = new FileInfo(“C:/log.txt”);

Page 34: метуказлабраб ооп 2011укр

34

Багато методів, що надаються класом FileInfo, аналогічні відповідним методам класу File, проте, оскільки клас File є статичним класом, він вимагає завдання рядкового параметра з місцеположенням файлу при кожному виклику методу.

Об'єкт FileStream

Об'єкт FileStream представляє потік, вказуючий на який-небудь файл на диску або на місцеположення в мережі. Хоча цей клас і володіє методами для читання з файлів і запису у файли байтів, частіше для виконання цих функцій вам доведеться звертатися до класів StreamReader і StreamWriter. Це відбувається тому, що клас FileStream оперує байтами і масивами байтів, тоді як класи Stream оперують символьними даними. Мати справу з символьними даними виявляється простішим, проте нам доведеться зіткнутися з деякими операціями, наприклад, з довільним доступом до файлів, які можуть здійснюватися тільки за допомогою об'єкту FileStream.

Існує декілька способів створення об'єкту FileStream. Його конструктор володіє великою кількістю перевантажень/версій, проте в найпростішому випадку він вимагає передачі двох аргументів – імені файлу і значення типа перераховного FileMode:

FileStream aFile = new FileStream(“Log.txt”, FileMode.OpenOrCreate);

У перераховного типа FileMode є декілька членів, які дозволяють задавати те, яким чином файл відкривається або створюється: Append, Create, CreateNew, Open, OpenOrCreate, Truncate. Допускається їх використання в різних поєднаннях.

Приведений вище приклад конструктора за умовчанням відкриває файл в режимі читання/запису. Для того, щоб задати інший рівень доступу, слід використовувати додатковий параметр – FileAccess:

FileStream aFile = new FileStream(“Log.txt”, FileMode.OpenOrCreate, FileAccess.Write);

Цей рядок коду відкриє файл з дозволом доступу на запис. Будь-яка спроба прочитати вміст цього файлу приведе до виникнення виняткової ситуації. Перераховний тип FileAccess володіє всього трьома значеннями: Read, Write і ReadWrite. Отже, є можливість відкрити файл тільки на читання, тільки на запис і на читання і запис одночасно.

Обидва класи File і FileInfo надають методи OpenRead() і OpenWrite(), які полегшують створення об'єктів FileStream. Перший метод відкриває файл з режимом доступу “тільки читання”, а другий, крім того, дозволяє здійснювати запис. Це дозволяє спростити звернення до файлу, так що вам тепер не доведеться указувати всю інформацію, як в попередніх прикладах. Наприклад, наступний рядок відкриває файл Data.txt у режимі “тільки читання”:

FileStream aFile = File.OpenRead(“Data.txt”);

Звернете увагу на те, що наступний код виконує ті ж самі дії:

FileInfo aFile = new FileInfo(“Data.txt”); FileStream aFile = aFile.OpenRead();

Позиція усередині файлу

Клас FileStream підтримує внутрішній покажчик файлу, що посилається на те місце у файлі, в якому проводитиметься чергова операція читання або запису. В більшості випадків при відкритті файлу покажчик встановлюється в початок файлу, проте така поведінка покажчика може бути змінена, що дозволяє здійснювати читання або запис в будь-якій точці файлу. Можна також організувати довільний доступ до файлу і здійснювати пошук конкретної позиції у файлі.

Метод, який реалізує дану функціональну можливість, носить назву Seek():

public long Seek(long offset, SeekOrigin origin);

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

Page 35: метуказлабраб ооп 2011укр

35

трьох значень: Begin (початок), Current (поточна позиція) End (кінець). Наступний рядок пересуває покажчик файлу на восьмий байт, рахуючи з найпершого байта даного файлу:

aFile.Seek(8, SeekOrigin.Begin);

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

aFile.Seek(-5, SeekOrigin.End);

Файли, доступ до яких може здійснюватися таким чином, часто називають файлами з довільним доступом, оскільки у застосування є можливість дістати доступ до будь-якої позиції у файлі. Класи Stream дозволяють здійснювати послідовний доступ до файлів, і в них не передбачена можливість роботи з покажчиками.

Читання даних

Читання даних з використанням класу FileStream виявляється не таким простим, як з використанням класів StreamReader і StreamWriter, до розгляду яких ми повернемося нижче. Це відбувається тому, що клас FileStream має справу виключно з байтами, що робить клас корисним при роботі з файлами довільного типу, а не тільки з текстовими файлами. Побайтне прочитування даних дозволяє використовувати цей клас при роботі з графічними і звуковими файлами. Проте платою за подібну гнучкість є неможливість за допомогою класу FileStream прочитувати дані безпосередньо змінні типу рядка. Це дозволяють здійснювати класи StreamWriter і StreamReader. Існує проте декілька конверсійних класів, які істотно полегшують виконання перетворення масиву байтів в символьні масиви і назад.

Метод FileStream.Read() є основним засобом, що дозволяє здійснювати доступ до даних, що містяться у файлі, на який посилається об'єкт FileStream.

public int Read(byte[] array, int offset, int count);

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

Вказівки до завдання 1.

Треба дати компонентам, поміщеним на форму, наприклад такі імена: openFile – для кнопки (Button), filename – для однорядкового текстового поля (TextBox), source – для багаторядкового текстового поля (TextBox), openFileDialog – для діалогу відкриття файлів (невізуальний компонент OpenFileDialog).

У властивості Filter компоненту openFileDialog прописати, наприклад “All files | *.*”.

В обробнику натиснення на кнопку openFile активізувати діалог відкриття файлу наступною командою:

openFileDialog.ShowDialog();

Створити обробник події FILEOK для компоненту openFileDialog. У цьому обробнику отримати ім'я файлу і відобразити це ім'я в текстовому полі:

string fullPathname = openFileDialog.FileName; FileInfo src = new FileInfo(fullPathname); filename.Text = src.Name; source.Text = "";

Далі працювати з об'єктом типа TextReader, прочитуючи рядки з файлу в циклі while і відображаючи їх в багаторядковому текстовому полі.

Page 36: метуказлабраб ооп 2011укр

36

Лабораторна робота №3. Обробка виключень в C#.

Мета роботи: засвоїти основи обробки виключень в мові C#, набути практичних навичок обробки виключень.

Завдання.

Удосконалити простий калькулятор (Лабораторна робота №1, завдання 3), ввівши в нього обробку виключень, пов'язаних з неправильним введенням даних.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати завдання.

Вправа 1.

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

// Демонстрація обробки виключень.

using System;

class ExcDemo1 { public static void Main(){ int[] nums = new int[4]; try { Console.WriteLine( “Перед генеруванням виключення.”); // генеруємо виключення, пов'язане з попаданням індексу поза діапазоном. for(int i=0; i<10; i++){ nums[i]= i; Console.WriteLine(“nums[{0}]: {1}”, i, nums[i]);

Page 37: метуказлабраб ооп 2011укр

37

}

Console.WriteLine(“Цей текст не відображається.”); } catch (IndexOutOfRangException) { //Перехоплюємо виключення.

Console.WriteLine(“Індекс поза діапазоном!”); } Console.WriteLine(“Після catch-інструкції.”); } }

Вправа 2.

Демонстрація блоків try ... catch ... finally. У циклі користувачеві пропонують ввести число із заданого діапазону, і потім це число виводиться на екран. Якщо введене число не належить заданому діапазону, то генерується виключення.

using System; namespace AdvancedCSharp {

public class MainEntryPoint {

public static void Main() { string userInput; while(true) {

try { Console.Write("Input а number between 0 and 5 " +

"(or just hit return to exit)> "); userInput = Console.ReadLine(); if(userInput == "") break;

int index = Convert.ToInt32(userInput); if(index < 0 || index > 5)

throw new IndexOutOfRangeException (

"You typed in " + userInput); Console.WriteLine("Your number was " + index);

} catch (IndexOutOfRangeException e) { Console.WriteLine("Exception: " +

"Number should be between 0 and 5. " + e.Message); } catch (Exception e) {

Console.WriteLine("An exception was thrown. Message was " + e.Message); } catch { Console.WriteLine("Some other exception has occurred");

} finally {

Console.WriteLine("Thank you"); } }

} } }

Page 38: метуказлабраб ооп 2011укр

38

Методичні вказівки та теоретичні відомості.

Виняткова ситуація (або виключення) – це помилка, яка виникає під час виконання програми. Використовуючи C#-подсистему обробки виняткових ситуацій, з такими помилками можна справлятися. Можливо, найпростішим прикладом є спроба звернутися до елементу масиву, що виходить за його межі:

int[] myArray = {1,2,3,4}; int myElem = myArray[4];

В результаті з'явиться приведене нижче повідомлення про виняткову ситуацію, а виконання застосування буде припинено:

An unhandled exception of type ‘System.IndexOutOfRangeException’ occurred in <file>.exe

Тут <file> – це ім'я файлу, в якому міститься дана виняткова ситуація.

Клас System.Exception

У C# виключення представляються класами. Всі класи виключень повинні бути виведені з вбудованого класу виключень Exception, який є частиною простору імен System.

Основи обробки виключень

У мові програмування C# передбачений спеціальний синтаксис для Structured Exception Handling (SEH – структурованої обробки виключень). Існують спеціальні ключові слова, що дозволяють позначати ділянки коду як ділянки, в яких допустима обробка виняткових ситуацій, і розміщувати інструкції, вказуючі, що слід робити при виникненні виняткової ситуації. Для цих цілей використовуються чотири ключові слова: try, catch, throw і finally. Кожному з них відповідає якийсь блок коду, і всі вони повинні поміщатися в послідовно розташованих рядках коду. Основна інструкція має наступний вигляд:

try{ . . . }

catch (<типВинятковоїСитуації> e) { . . . } finally{ . . . }

Існує також можливість використовувати блоки try та finally без блоку catch, а також блок try з декількома блоками catch. Якщо є один або декілька блоків catch, то блок finally є необов'язковим, інакше він обов'язковий.

Ці блоки використовуються таким чином:

• try містить код, який може привести до виникнення виняткової ситуації.

• catch містить код, який повинен виконуватися у разі виникнення виняткової ситуації. Блоки catch можуть бути настроєні так, щоб реагувати тільки на один конкретний тип виняткової ситуації (наприклад, на System.IndexOutOfRangeException), для чого використовується параметр <типВинятковоїСитуації>, оскільки існує можливість одночасно встановити декілька блоків catch. Але можна і взагалі опустити цей параметр, тоді вийде загальний блок catch, який реагуватиме на всі види виняткових ситуацій.

• finally містить блок коду, який виконується завжди: або після виконання блоку try, якщо не виникло ніяких виняткових ситуацій, або після блоку catch, якщо проводилася обробка

Page 39: метуказлабраб ооп 2011укр

39

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

Події, що відбуваються після виникнення виняткової ситуації в блоці коду try, мають таку послідовність:

• Виконання блоку try припиняється в тій точці, в якій виникла виняткова ситуація.

• Якщо існує блок catch, то проводиться перевірка на предмет того, чи співпадає його параметр з типом виниклої виняткової ситуації. Якщо блок catch відсутній, то виконується блок finally (який в цьому випадку є обов'язковим).

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

• Якщо параметр блоку catch співпадає з типом виниклої виняткової ситуації, то спочатку виконується код, що міститься в блоці, а потім – у випадку, якщо він присутній, - виконується блок finally.

• Якщо жоден з блоків catch не відповідає типу виниклої виняткової ситуації, то виконується блок finally (якщо він існує).

Щоб згенерувати виключення вручну, використовується ключове слово throw. Синтаксис його використання такий:

throw exceptOb;

Елемент – це об'єкт класу виключень, похідного від класу Exception.

Розглянемо приклад, який демонструє використання інструкції throw для генерування виключення типа DivideByZeroException уручну.

using System; class ThrowDemo { public static void Main(){ try { Console.WriteLine(“До генерування виключення.”); throw new DivideByZeroException(); }

catch (DivideByZeroException){ //Перехоплюємо виключення Console.WriteLine(“Виключення перехоплене.”);

} Console.WriteLine(“Після try/catch-блока.”);

} }

І ще один приклад.

using System; class TestMain { private static void Test() // Run time error { for(int i=-10;i<=10;++i) int y=100/i; } } public static void Main( ) { try { Test(); } catch {

Page 40: метуказлабраб ооп 2011укр

40

Console.WriteLine("Got an exception...."); } } }

Лабораторна робота №4. Використання масивів і колекцій. Класи ArrayList,

Queue, Stack, Hashtable, SortedList.

Мета роботи: засвоїти основи використання масивів і колекцій в мові C#, набути практичних навичок роботи з двовимірними масивами.

Варіанти завдання.

Варіант 1. Дана цілочисельна прямокутна матриця. Визначити: 1) кількість рядків, що не містять жодного нульового елементу; 2) максимальне з чисел, що зустрічаються в заданій матриці більше одного разу.

Варіант 2. Дана цілочисельна прямокутна матриця. Визначити кількість стовпців, що не містять жодного нульового елементу.

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

Варіант 3. Дана цілочисельна квадратна матриця. Визначити: 1) добуток елементів в тих рядках, які не містять негативних елементів; 2) номер рядка, в якому знаходиться найдовша серія однакових елементів.

Варіант 4. Серед тих рядків цілочисельної матриці, які містять тільки непарні елементи, знайти рядок з максимальною сумою модулів елементів.

Варіант 5. Підрахувати кількість рядків заданої цілочисельної матриці NхN, що є перестановкою чисел 1,2...N (тобто що містять кожне з чисел 1,2...N рівно один раз).

Варіант 6. Серед стовпців заданої цілочисельної матриці, що містять тільки такі елементи, які по модулю не більше 10, знайти стовпець з мінімальним добутком елементів.

Варіант 7.

Масивом char а[M][N] кодується поле, на якому розташовано декілька прямокутників. Кожен складається з цілого числа кліток, різні прямокутники не накладаються один на одного і не стикаються. Різні прямокутники можуть складатися з різних символів. Один і той же прямокутник не може складатися з різних символів. Порожні квадрати поля кодується символом '.'. Підрахувати число прямокутників різних типів. Поле вводиться з клавіатури або читається з файлу. Приклад: ###...??..+. ###.=.??..+. ###.......+. .....???.... ???.......== ???...####.. Для цього поля програма повинна видати відповідь: #-прямоугольников: 2 ?-прямоугольников: 3 +-прямоугольников: 1 =-прямоугольников: 2

Page 41: метуказлабраб ооп 2011укр

41

Варіант 8. Характеристикою стовпця цілочисельної матриці назвемо суму модулів його негативних непарних елементів. Переставляючи стовпці заданої матриці, розташувати їх відповідно до зростання характеристик.

Варіант 9. Для заданої матриці розміром NхN знайти таке k, що k-й рядок матриці співпадає з k-м стовпцем.

Варіант 10. Починаючи з центру, обійти по спіралі всі елементи матриці NхN, роздруковувавши їх в порядку обходу.

Варіант 11. Для заданої цілочисельної квадратної матриці знайти максимум серед сум елементів діагоналей, що паралельні головній діагоналі.

Варіант 12. Починаючи з елементу a11 обійти по спіралі квадратну матрицю NхN, роздруковувавши елементи в порядку обходу.

Варіант 13. Знайти максимальний серед всіх елементів тих рядків заданої матриці, які впорядковані (або за збільшенням, або за зменшенням).

Варіант 14. По заданій квадратній матриці NхN побудувати вектор завдовжки 2n-1, елементи якого – максимуми елементів діагоналей, паралельних головній.

Варіант 15. Дана цілочисельна квадратна матриця. Визначити: 1) суму елементів в тих стовпцях, які не містять негативних елементів; 2) мінімум серед сум модулів елементів діагоналей, паралельних побічній діагоналі матриці.

Варіант 16. Дана цілочисельна прямокутна матриця. Визначити:

1) суму елементів в тих рядках, які містять хоч би один негативний елемент; 2) номери рядків і стовпців всіх сідлових точок матриці.

Примітка. Матриця А має сідлову точку Аij, якщо Аij є мінімальним елементом в i-й рядку і максимальним в j-м стовпці.

Варіант 17. Ущільнити задану матрицю, видаляючи з неї рядки і стовпці, заповнені нулями. Знайти номер першою з рядків, що містять хоч би один позитивний елемент.

Варіант 18. Дана цілочисельна прямокутна матриця. Визначити: 1) кількість рядків, що містять хоч би один нульовий елемент; 2) номер стовпця, в якому знаходиться найдовша серія однакових елементів.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати завдання згідно своєму варіанту.

Вправа 1.

Приклад використання ArrayList.

using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace ArrayList2 { class Program { static void Main(string[] args)

Page 42: метуказлабраб ооп 2011укр

42

{ ArrayList baseballTeams = new ArrayList(); baseballTeams.Add("St. Louis Cardinals"); baseballTeams.Add("Seattle Mariners"); baseballTeams.Add("Florida Marlins"); string[] myStringArray = new string[2]; myStringArray[0]= "San Francisco Giants"; myStringArray[1]= "Los Angeles Dodgers"; baseballTeams.AddRange(myStringArray); foreach (string item in baseballTeams) { Console.Write(item + "\n"); } Console.ReadLine(); } } }

Вправа 2.

Приклад використання класу Hashtable.

using System; using System.Text; using System.Collections; namespace SocialSecurityNumbers { class MainEntryPoint { static void Main() { TestHarness harness = new TestHarness(); harness.Run(); } } class TestHarness { Hashtable employees = new Hashtable(31); public void Run() { EMPLOYEEID idMortimer = new EMPLOYEEID("B001"); EmployeeData mortimer = new EmployeeData(idMortimer, "Mortimer", 100000.00M); EMPLOYEEID idArabel = new EMPLOYEEID("W234"); EmployeeData arabel= new EmployeeData(idArabel, "Arabel Jones", 10000.00M); employees.Add(idMortimer, mortimer); employees.Add(idArabel, arabel); while (true) { try { Console.Write("Enter employee ID (format:A999, X to exit)> "); string userInput = Console.ReadLine(); userInput = userInput.ToUpper(); if (userInput == "X")

Page 43: метуказлабраб ооп 2011укр

43

return; EMPLOYEEID id = new EMPLOYEEID(userInput); DisplayData(id); } catch (Exception e) { Console.WriteLine("Exception occurred. Did you use the correct format for the employee ID?"); Console.WriteLine(e.Message); Console.WriteLine(); } Console.WriteLine(); } } private void DisplayData(EMPLOYEEID id) { object empobj = employees[id]; if (empobj != null) { EmployeeData employee = (EmployeeData)empobj; Console.WriteLine("Employee: " + employee.ToString()); } else Console.WriteLine("Employee not found: ID = " + id); } } class EmployeeData { private string name; private decimal salary; private EMPLOYEEID id; public EmployeeData(EMPLOYEEID id, string name, decimal salary) { this.id = id; this.name = name; this.salary = salary; } public override string ToString() { StringBuilder sb = new StringBuilder(id.ToString(), 100); sb.Append(": "); sb.Append(string.Format("{0-20}", name)); sb.Append(" "); sb.Append(string.Format("{0:C}", salary)); return sb.ToString(); } } class EMPLOYEEID { private readonly char prefix; private readonly int number; public EMPLOYEEID(string id) { prefix = (id.ToUpper())[0]; number = int.Parse(id.Substring(1,3)); }

Page 44: метуказлабраб ооп 2011укр

44

public override string ToString() { return prefix.ToString() + string.Format("{0,3:000}", number); } public override int GetHashCode() { string str = this.ToString(); return str.GetHashCode(); } public override bool Equals(object obj) { EMPLOYEEID rhs = obj as EMPLOYEEID; if (rhs == null) return false; if (prefix == rhs.prefix && number == rhs.number) return true; return false; } } }

Методичні вказівки і теоретичні відомості.

Масиви

Масив (array) – це сукупність змінних однакового типу, звернення до яких відбувається з використанням загального для всіх імені. У C# масиви можуть бути одновимірними або багатовимірними.

Хоча масиви в C# можна використовувати по аналогії з тим, як вони використовуються в інших мовах програмування, C#-массивы мають один спеціальний атрибут, а саме: вони реалізовані як об'єкти.

Приклад #1: Одновимірний масив. class TestMain { public static int Main() { int[] ar; // Declare array ar= new int[20]; // new space on heap for(int i=0;i<ar.Length;++i) // Length Attribute ar[i]=i; } for(int i=0;i<ar.Length;++i) System.Console.WriteLine("Item ["+i+"]="+ar[i]); } return 0; } } Приклад #2: Двовимірний масив. Рвані масиви. class TestMain { public static int Main() {

Page 45: метуказлабраб ооп 2011укр

45

int[][] ar; // Declare array 2dim ar= new int[20][] ; for(int i=0;i<ar.Length;++i) { ar[i]=new int[1+i]; } for(int i=0;i<ar.Length;++i) { for(int k=0;k<ar[i].Length;++k) ar[i][k]=0; } } return 0; } } Приклад #3: Двовимірні масиви. Прямокутні масиви. class TestMain { public static int Main() { int[,] ar; ar= new int[5,20]; System.Console.WriteLine("Item: "+ar.Length);//total Items in 2-D Array int rows=ar.GetLength(0); int cols=ar.GetLength(1); System.Console.Write("Rows="+rows+" Cols="+cols); return 0; } } Приклад #4: Масив об'єктів.

using System; public class Car { private String mName; public void Info() { Console.WriteLine("Name: " + mName); } public Car(String name){ mName=name; } } class TestMain { public static int Main() Car[] ar; ar=new Car[100]; // allocate array object for(int i=0;i<ar.Length;++i) ar[i]=new Car("Car #"+i); } for(int i=0;i<ar.Length;++i) { ar[i].Info(); } return 0; } }

Page 46: метуказлабраб ооп 2011укр

46

Робота з колекціями

У C# під колекцією мається на увазі група об'єктів. Простір імен System.Collections містить ряд інтерфейсів і класів, які визначають і реалізують колекції різних типів. Колекції спрощують програмування, пропонуючи вже готові рішення для побудови структур даних, розробка яких «з нуля» відрізняється великою трудомісткістю. Йдеться про вбудовані колекції, які підтримують, наприклад, функціонування стеків, черг і хеш-таблиць.

Середовище .NET Framework підтримує три основні типи колекцій: загального призначення, спеціалізовані і орієнтовані на побітову організацію даних. Колекції загального призначення реалізують ряд основних структур даних, включаючи динамічний масив, стек і чергу. Сюди також відносяться словники, призначені для зберігання пар ключ/значення. Колекції загального призначення працюють з даними типу object, тому їх можна використовувати для зберігання даних будь-якого типа.

Колекції спеціального призначення орієнтовані на обробку даних конкретного типу або на обробку унікальним способом. Наприклад, існують спеціалізовані колекції, призначені тільки для обробки рядків або однонаправленого списку.

Основою для всіх колекцій є реалізація нумератора, який підтримує інтерфейси IEnumerator і IEnumerable. Нумератор забезпечує стандартний спосіб поелементного доступу до вмісту колекції.

Інтерфейси колекцій.

У просторі імен System.Collections визначена велика кількість інтерфейсів. Інтерфейси колекцій визначають функції, загальні для всіх класів колекцій.

Інтерфейс ICollection.

Інтерфейс ICollection можна назвати фундаментом, на якому побудовані всі колекції. У нім оголошені основні методи і властивості, без яких не може обійтися жодна колекція. Він успадковує інтерфейс IEnumerable. Не знаючи суті інтерфейсу ICollection, неможливо зрозуміти механізм дії колекцій.

У інтерфейсі ICollection визначені наступні властивості:

Таблиця 5. Властивості інтерфейсу ICollection.

Властивість Опис

int Count{get;} Кількість елементів колекції в даний момент

bool IsSynchronized{get;} Приймає значення true, якщо колекція синхронізована, інакше значення false. За замовчуванням колекція не синхнонізована.

object SyncRoot{get;} Об’ект, для якого колекція може бути синхронізована.

Властивість Count – сама затребувана, оскільки містить кількість елементів, що зберігаються в колекції в даний момент. Якщо властивість Count дорівнює нулю, це означає, що колекція порожня. У інтерфейсі визначений наступний метод:

void CopyTo(Array target, int startIdx)

Метод CopyTo() копіює вміст колекції в масив, заданий параметром target, починаючи з індексу, заданого параметром startIdx.

Оскільки інтерфейс ICollection успадковує інтерфейс IEnumerable, він також включає його єдиний метод GetEnumerator():

IEnumerator GetEnumerator()

Цей метод повертає нумератор колекції.

Page 47: метуказлабраб ооп 2011укр

47

Інтерфейс IList.

Інтерфейс IList успадковує інтерфейс ICollection і визначає поведінку колекції, доступ до елементів якої дозволений за допомогою індексу з відліком від нуля. Крім методів, визначених в інтерфейсі ICollection, інтерфейс IList визначає і власні методи.

Об'єкти додаються в колекцію типа IList за допомогою виклику методу int Add(object obj). Зверніть увагу на те, що метод Add() приймає аргументи типу object. Оскільки клас object є базовим для всіх типів, в колекції можна зберегти об'єкт будь-якого типу.

Видалити об'єкт з колекції можна за допомогою методу Remove() або RemoveAt(). Для повного очищення колекції досить викликати метод Clear().

Щоб дізнатися, чи містить колекція заданий елемент, викличте метод Contains(). Отримати індекс заданого об'єкту допоможе метод IndexOf(), а вставити елемент по заданому індексу – метод Insert().

У класі IList визначений наступний індексатор:

object this[int idx] { get; set; }

Цей індексатор можна використовувати для прочитування або запису значення потрібного елементу. Але його не можна застосувати для додавання в колекцію нового елементу. Для цієї мети існує метод Add().

Інтерфейс IDictionary.

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

Щоб додати пару ключ/значення в IDictionary-колекцію, використовуйте метод void Add(object k, object v). Зверніть увагу на те, що ключ і його значення задаються як окремі параметри. Щоб видалити з колекції-словника непотрібний елемент, необхідно передати методу Remove() відповідний йому ключ. Для очищення всієї колекції використовується метод Clear(). Щоб визначити, чи містить колекція заданий об'єкт, досить викликати метод Contains(), передавши йому ключ елементу, що цікавить вас. Метод GetEnumerator() повертає нумератор, сумісний з колекцією IDictionary.

У інтерфейсі IDictionary визначені наступні властивості:

Таблиця 6. Властивості інтерфейсу IDictionary.

Властивість Опис

bool IsFixedSize{get; } дорівнює значенню true, якщо словник має фіксований розмір

bool IsReadOnly{get; } дорівнює значенню true, якщо словник тільки для

ICollection Keys{get; } Отримує колекцію ключів

ICollection Values{get; } Отримує колекцію значень

Зверніть увагу на те, що за допомогою властивостей Keys та Values ключі та значення, що зберігаються в словарній колекції, можна отримати у вигляді окремих списків.

Клас ArrayList

Клас ArrayList призначений для підтримки динамічних масивів, які при необхідності можуть збільшуватися або скорочуватися. У C# стандартні масиви мають фіксовану довжину, яка не може змінюватися під час виконання програми.

Page 48: метуказлабраб ооп 2011укр

48

Об'єкт класу ArrayList є масив змінної довжини, елементами якого є об'єктні посилання. Будь-який об'єкт класу ArrayList створюється з деяким початковим розміром. При перевищенні цього розміру колекція автоматично його збільшує. У разі видалення об'єктів масив можна скоротити. Колекція класу ArrayList, мабуть, найбільш вживана.

Клас ArrayList реалізує інтерфейси ICollection, IList, IEnumerable і ICloneable. У класі ArrayList визначені наступні конструктори:

public ArrayList()

public ArrayList(ICollection c)

public ArrayList(int capacity)

Перший конструктор призначений для створення порожнього ArrayList-масиву з початковою місткістю, рівною 16 елементам. Другий служить для побудови масиву, який ініціалізувався елементами і місткістю колекції, заданої параметром c. Третій конструктор створює масив із заданою початковою місткістю. Місткість – це розмір масиву для зберігання елементів. При додаванні елементів кожного разу, коли масив повинен автоматично розширитися, його місткість подвоюється.

Крім методів, визначених в інтерфейсах, які реалізує клас ArrayList, в нім визначені і власні методи. Найбільш вживані з них перераховані в Таблиці 7.

Таблиця 7. Найбільш вживані методи класу ArrayList.

Метод Опис

public virtual void AddRange(ICollection c)

Додає элементи з колекції c в кінець колекції

public virtual int BinarySearch(object v)

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

public virtual void CopyTo(Array ar, int startIdx)

Копіює вміст колекції, починаюци з startIdx, в масив

public virtual void Sort() Сортує колекцію за збільшенням

public virtual void Reverse() Розміщує елементи колекциії в зворотньому порядку

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

Клас Hashtable

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

Клас Hashtable реалізує інтерфейси IDictionary, ICollection, IEnumerable, ISerializable, ICloneable.

У класі Hashtable визначена велика кількість конструкторів, включаючи наступні (вони використовуються найчастіше):

public Hashtable()

public Hashtable(IDictionary c)

public Hashtable(int capacity)

Page 49: метуказлабраб ооп 2011укр

49

public Hashtable(int capacity, float fillRatio)

Перша форма дозволяє створити стандартний об'єкт класу Hashtable. Друга для ініціалізації Hashtable-об'єкту використовує елементи заданої колекції c. Третя ініціалізує місткість створюваної хеш-таблиці значенням capacity, а четверта – як місткість (значенням capacity), так і коефіцієнт заповнення (значенням fillRatio). Значення коефіцієнта заповнення (також іменованого коефіцієнтом навантаження), яке повинне потрапляти в діапазон 0,1-1,0, визначає ступінь заповнення хеш-таблиці, після чого її розмір збільшується.

У класі Hashtable крім методів, визначених в реалізованих ним інтерфейсах, також визначені власні методи. Так, щоб визначити, чи містить Hashtable-колекція заданий ключ, досить викликати метод ContainsKey(). А щоб дізнатися, чи зберігається в хеш-таблиці задане значення, що цікавить вас, викличте метод ContainsValues(). Для опиту елементів Hashtable-колекції необхідно отримати нумератор типу IdictionaryEnumerator, викликавши метод GetEnumerator().

Приклад #1: System.Collections.IDictionary + Hash table

using System; public class TestMain { public static void Main() { System.Collections.IDictionary dict=new System.Collections.Hashtable(); dict.Add("One",123); dict.Add("two","Hello WOrld"); dict.Add(33,1234.5554); dict.Add("me","[email protected]"); Console.WriteLine("Item Count: " + dict.Count ); foreach(object keys in dict.Keys) Console.WriteLine("Key: {0} Value: {1} ",keys,dict[keys]); } if (dict.Contains("me")) { Console.WriteLine("key me is in collection"); } dict.Remove("me"); // Remove Keyed Element dict.Clear(); // Clear all items } } Приклад #2: List Dictionary (single Linked list)

using System; public class TestMain { public static void Main() { System.Collections.IDictionary dict=new System.Collections.Specialized.ListDictionary(); dict.Add("One",123); dict.Add("two","Hello WOrld"); dict.Add(33,1234.5554); dict.Add("me","[email protected]"); Console.WriteLine("Item Count: " + dict.Count ); foreach(object keys in dict.Keys) Console.WriteLine("Key: {0} Value: {1} ",keys,dict[keys]); } if (dict.Contains("me")) { Console.WriteLine("key me is in collection"); }

Page 50: метуказлабраб ооп 2011укр

50

dict.Remove("me"); // Remove Keyed Element dict.Clear(); // Clear all items } }

Клас SortedList

Клас SortedList призначений для створення колекції, яка зберігає пари ключ/значення у впорядкованому вигляді, а саме вони відсортовані по ключу. Клас SortedList реалізує інтерфейси IDictionary, ICollection, IEnumerable і ICloneable.

У класі SortedList визначено декілька конструкторів, включаючи наступні:

public SortedList()

public SortedList(IDictionary c)

public SortedList(int capacity)

public SortedList(Icomparer comp)

Перший конструктор дозволяє створити порожню колекцію з початковою місткістю, рівною 16 елементам. Другий створює SortedList-колекцію, яка ініціалізувалася елементами і місткістю колекції, заданої параметром c. Третій конструктор призначений для побудови порожнього SortedList-списку, який ініціалізувався місткістю, заданою параметром capacity. Четверта форма конструктора дозволяє задати метод порівняння, який повинен використовуватися для порівняння об'єктів списку. За допомогою цієї форми створюється порожня колекція з початковою місткістю, рівною 16 елементам.

Існують різні способи установки і прочитування ключа або значення. Щоб набути значення, пов'язаного із заданим індексом, викличте метод GetByIndex(), а щоб встановити значення, задане індексом, - метод SetByIndex(). Отримати ключ, пов'язаний із заданим індексом, можна за допомогою методу GetKey(). Для отримання списку всіх ключів використовуйте метод GetKeyList(), а для отримання списку всіх значень – метод GetValueList().

Розглянемо приклад використання класу SortedList.

using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace SortedList1 { class Program { static void Main(string[] args) { SortedList footballTeams = new SortedList(); footballTeams.Add(1, "St. Louis Rams"); footballTeams.Add(2, "Kansas City Chiefs"); footballTeams.Add(3, "Indianapolis Colts"); for (int i = 0; i < footballTeams.Count; i++) { Console.WriteLine("KEY: " + footballTeams.GetKey(i) + " VALUE: " + footballTeams.GetByIndex(i)); } Console.ReadLine(); } } }

Page 51: метуказлабраб ооп 2011укр

51

Клас Stack

Клас колекції, призначений для підтримки стека, називається Stack. Він реалізує інтерфейси ICollection, IEnumerable та IСloneable. Стек – це динамічна колекція, яка при необхідності збільшується, щоб прийняти для зберігання нові елементи, причому кожного разу, коли стек повинен розширитися, його місткість подвоюється.

У класі Stack визначені наступні конструктори:

public Stack()

public Stack(int capacity)

public Stack(ICollection c)

Перший конструктор призначений для створення порожнього стека з початковою місткістю, рівною 10 елементам. Другий створює порожній стек з початковою місткістю, заданою параметром capacity. Третій конструктор служить для побудови стека, який ініціалізувався елементами і місткістю колекції, заданої параметром c.

Крім методів, визначених в інтерфейсах, які реалізує клас Stack, в нім визначені також власні методи, перераховані в Таблиці 8.

Таблиця 8. Методи, визначені в класі Stack.

Метод Опис

public virtual bool Contains(object v)

Повертає значення true, якщо об'єкт v міститься в стеку. Інакше повертає значення false.

public virtual void Clear() Встановлює властивість Count рівною нулю, тим самим ефективно очищаючи стек.

public virtual object Peek() Повертає елемент, розташований у вершині стека, але не видаляє його

public virtual object Pop() Повертає елемент, розташований у вершині стека, і видаляє його

public virtual void Push(object v) Поміщає об'єкт v в стек

public static Stack Synchronized(Stack stk)

Повертає синхронізовану версію Stack-списку, переданого в параметрі stk

public virtual object[] ToArray() Повертає масив, який містить копії елементів стека

Розглянемо приклад створення і використання стека. using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace Stack2 { class Program { static void Main(string[] args) { Stack alphabet = new Stack(); alphabet.Push("A"); alphabet.Push("B"); alphabet.Push("C"); Console.Write("First Iteration: "); foreach (string item in alphabet) { Console.Write(item); }

Page 52: метуказлабраб ооп 2011укр

52

Console.WriteLine("\nItem pulled from collection: " + alphabet.Pop().ToString()); Console.Write("Second iteration: "); foreach (string item in alphabet) { Console.Write(item); } Console.ReadLine(); } } }

Клас Queue

Клас колекції, призначений для підтримки черги, називається Queue. Він реалізує інтерфейси ICollection, IEnumerable та IСloneable. Черга – це динамічна колекція, яка при необхідності збільшується, щоб прийняти для зберігання нові елементи, причому кожного разу, коли така необхідність виникає, поточний розмір черги умножається на коефіцієнт зростання, який за умовчанням дорівнює значенню 2,0.

У класі Queue визначені наступні конструктори:

public Queue()

public Queue(int capacity)

public Queue(int capacity, float growFact)

public Queue(ICollection c)

Перший конструктор призначений для створення порожньої черги з початковою місткістю, рівною 32 елементам, і коефіцієнтом зростання 2,0. Другий створює порожню черга з початковою місткістю, заданою параметром capacity, і коефіцієнтом зростання 2,0. Третій відрізняється від другого тим, що дозволяє задати коефіцієнт зростання за допомогою параметра growFact. Четвертий конструктор служить для створення черги, яка ініціалізувалася елементами і місткістю колекції, заданої параметром c.

Крім методів, визначених в інтерфейсах, які реалізує клас Queue, в нім визначені також власні методи. Щоб помістити об'єкт в чергу, викличте метод Enqueue(). Щоб витягнути верхній елемент і видалити його з черги, використовуйте метод Dequeue(). Метод Peek() дозволяє повернути наступний об'єкт, не видаляючи його з черги.

Розглянемо приклад, в якому демонструється використання класу Queue. using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace Queue1 { class Program { static void Main(string[] args) { Queue alphabet = new Queue(); alphabet.Enqueue("A"); alphabet.Enqueue("B"); alphabet.Enqueue("C"); Console.Write("First Iteration: "); foreach (string item in alphabet) {

Page 53: метуказлабраб ооп 2011укр

53

Console.Write(item); } Console.WriteLine("\nItem pulled from collection: " + alphabet.Dequeue().ToString()); Console.Write("Second iteration: "); foreach (string item in alphabet) { Console.Write(item); } Console.ReadLine(); } } }

Лабораторна робота №5. Класи в C#. Спадкування.

Мета роботи: засвоїти основи побудови ієрархії класів на мові C#, набути практичних навичок використання прийомів об'єктно-орієнтованого програмування.

Варіанти завдання.

1. Перелік класів: Студент, Викладач, Персона, Зав. кафедрою.

2. Перелік класів: Службовець, Персона, Робочий, Інженер.

3. Перелік класів: Робочий, Кадри, Інженер, Адміністрація.

4. Перелік класів: Деталь, Механізм, Виріб, Вузол.

5. Перелік класів: Організація, Страхова компанія, Суднобудівельна компанія, Завод.

6. Перелік класів: Журнал, Книга, Друкарське видання, Підручник.

7. Перелік класів: Тест, Іспит, Випускний іспит, Випробування.

8. Перелік класів: Місце, Область, Місто, Мегаполіс.

9. Перелік класів: Іграшка, Продукт, Товар, Молочний продукт.

10. Перелік класів: Квитанція, Накладна, Документ, Чек.

11. Перелік класів: Автомобіль, Потяг, Транспортний засіб, Експрес.

12. Перелік класів: Двигун, Двигун внутрішнього згорання, Дизель, Турбореактивний двигун.

13. Перелік класів: Республіка, Монархія, Королівство, Держава.

14. Перелік класів: Ссавці, Парнокопитні, Птахи, Тварина.

15. Перелік класів: Корабель, Пароплав, Парусник, Корвет.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Визначити ієрархію класів (відповідно до варіанту завдання).

4. Для визначення ієрархії класів потрібно зв'язати відношенням спадкоємства класи, приведені у варіанті завдання лабораторної роботи. З перерахованих класів вибрати один, який стоятиме на чолі ієрархії. Це буде абстрактний клас.

5. Визначити в класах всі необхідні конструктори і деструкцію.

Page 54: метуказлабраб ооп 2011укр

54

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

7. Реалізувати класи.

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

Вправа 1.

Приклад #1: Class + new operator using System; class Car { private String mName; //Constructor public Car(){ mName="No Name"; } //Constructor public Car(String name) { mName=name; } //Destructor ~Car() Console.WriteLine("Disposing of "+mName); } // Member Method public void Print() { Console.WriteLine("Name : " + mName); } } class TestMain { public static void Main( ) { for(int i=0;i<9000;++i) { Car a=new Car("Name:"+i); а.Print(); } } }

Вправа 2.

Приклад #1: Пізнє скріплення і віртуальні функції

using System; public class Base { public void PrintItem() { for(int i=0;i<10;++i) // Is There Late Binding????

Page 55: метуказлабраб ооп 2011укр

55

Console.WriteLine("Item: "+this.GetItem(i) ); } } public virtual int GetItem(int index) { return 0; } } public class Derived:Base { public override int GetItem(int index) //*override* { return index*index; } } public class TestMain { public static void Main() { new Derived().PrintItem(); } } Приклад #2 Абстрактні методи

using System; public abstract class Base { public void PrintItem() { for(int i=0;i<10;++i) // Is There Late Binding???? Console.WriteLine("Item: "+this.GetItem(i) ); } } abstract public int GetItem(int index); // No } public class Derived:Base { override public int GetItem(int index) { return index*index; } } public class TestMain { public static void Main() { new Derived().PrintItem(); } }

Методичні вказівки та теоретичні відомості.

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

Page 56: метуказлабраб ооп 2011укр

56

Визначення класу

Клас - це тип даних, який задає реалізацію деякої абстракції даних, характерної для завдання, на користь якого створюється програмна система [30]. Клас створюється за допомогою ключового слова class. Загальна форма визначення класу, який містить тільки змінні і методи, має наступний вигляд:

class имя_класса { // Оголошення змінних екземплярів.

доступ тип переменная1; доступ тип переменная2; // . . . доступ тип переменнаяN; // Оголошення методів. доступ тип_возврата метод1(параметри){ // тіло методу } доступ тип_возврата метод2(параметри){ // тіло методу } // . . . доступ тип_возврата методN(параметри){ // тіло методу } }

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

[атрибути][модифікатори]class им’я_класу[:список_батьків] { тіло_класу}

Атрибути будуть розглянуті дещо пізніше. Можливими модифікаторами в оголошенні класу можуть бути модифікатори new, abstract, sealed, про яких говоритимемо при розгляді спадкоємства, та чотири модифікатори доступу (private, protected, public, internal), два з яких - private і protected - можуть бути задані тільки для вкладених класів. Зазвичай клас має атрибут доступу public, що є значенням за умовчанням.

У тілі класу можуть бути оголошені:

o константи; o поля; o конструктори і деструкції; o методи; o події; o делегати; o класи (структури, інтерфейси, перерахування).

Поля класу.

Основу будь-якого класу складають його конструктори, поля і методи. Поля класу синтаксично є звичайними змінними (об'єктами) мови. Їх опис задовольняє звичайним правилам оголошення змінних. Змістовно поля задають представлення тієї самої абстракції даних, яку реалізує клас. Поля характеризують властивості об'єктів класу.

Кожне поле має модифікатор доступу, що приймає одне з чотирьох значень: public, private, protected, internal. Атрибутом доступу за умовчанням є атрибут private. Незалежно від значення атрибуту доступу, всі поля доступні для всіх методів класу. Вони є для методів класу глобальною інформацією, з якою працюють всі методи, витягуючи з полів потрібні їм дані і змінюючи їх значення в ході роботи. Якщо поля доступні тільки для методів класу, то вони мають атрибут

Page 57: метуказлабраб ооп 2011укр

57

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

Якщо деякі поля класу A повинні бути доступні для методів класу B, що є нащадком класу A, то ці поля слід забезпечити атрибутом protected. Такі поля називаються захищеними. Якщо деякі поля повинні бути доступні для методів класів B1, B2 і так далі, дружніх по відношенню до класу A, то ці поля слід забезпечити атрибутом internal, а всі дружні класи B помістити в один проект (assembly). Такі поля називаються дружніми. Нарешті, якщо деякі поля повинні бути доступні для методів будь-якого класу B, якому доступний сам клас A, то ці поля слід забезпечити атрибутом public. Такі поля називаються загальнодоступними або відкритими.

Методи класу

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

Кожен метод має модифікатор доступу, що приймає одне з чотирьох значень: public, private, protected, internal. Атрибутом доступу за умовчанням є атрибут private. Незалежно від значення атрибуту доступу, всі методи доступні для виклику при виконанні методу класу. Якщо методи мають атрибут доступу private, можливо, опущений, то тоді вони доступні тільки для виклику лише усередині методів самого класу. Такі методи вважаються закритими. Зрозуміло, що клас, у якого всі методи закриті, абсурдний, оскільки ніхто не зміг би викликати жоден з його методів. Як правило, у класу є відкриті методи, що задають інтерфейс класу, і закриті методи. Інтерфейс - це обличчя класу і саме він визначає, чим клас цікавий своїм клієнтам, що він може робити, які сервіси надає клієнтам. Закриті методи складають важливу частину класу, дозволяючи клієнтам не вникати в багато деталей реалізації. Ці методи клієнтам класу недоступні, вони про них можуть нічого не знати, і, найголовніше, зміни в закритих методах ніяк не відбиваються на клієнтах класу за умови коректної роботи відкритих методів.

Якщо деякі методи класу A повинні бути доступні для викликів в методах класу B, що є нащадком класу A, то такі методи слід забезпечити атрибутом protected. Якщо деякі методи повинні бути доступні тільки для методів класів B1, B2 і так далі, дружніх по відношенню до класу A, то такі методи слід забезпечити атрибутом internal, а всі дружні класи B помістити в один проект. Нарешті, якщо деякі методи повинні бути доступні для методів будь-якого класу B, якому доступний сам клас A, то такі методи забезпечуються атрибутом public.

Методи-властивості

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

o читання, запис (Read, Write); o читання, запис при першому зверненні (Read, Write-once); o тільки читання (Read-only); o тільки запис (Write-only); o ні читання, ні запис (Not Read, Not Write).

Загальнодоступність властивостей (атрибут public) дозволяє реалізувати тільки першу стратегію. У мові C# прийняте, як і в інших об'єктних мовах, властивості оголошувати закритими, а потрібну стратегію доступу організовувати через методи. Для ефективності цього процесу і введені спеціальні методи-властивості.

Розглянемо, наприклад, клас Person, у якого п'ять полий: fam, status, salary, age, health, що характеризують відповідно прізвище, статус, зарплату, вік і здоров'я персони. Для кожного з цих

Page 58: метуказлабраб ооп 2011укр

58

полів може бути розумною своя стратегія доступу. Вік доступний для читання і запису, прізвище можна задати тільки один раз, статус можна тільки читати, зарплата недоступна для читання, а здоров'я закрите для доступу і лише спеціальні методи класу можуть повідомляти деяку інформацію про здоров'я персони. От як на C# можна забезпечити ці стратегії доступу до закритих полів класу [30]:

public class Person { //поля (всі закрито) string fam="", status="", health=""; int age=0, salary=0; //методи - властивості /// <summary> ///стратегія: Read,Write-once (Читання, запис при першому зверненні) /// </summary> public string Fam { set {if (fam == "") fam = value;} get {return(fam);} } /// <summary> ///стратегія: Read-only(Тільки читання) /// </summary> public string Status { get {return(status);} } /// <summary> ///стратегія: Read,Write (Читання, запис) /// </summary> public int Age { set { age = value; if(age < 7) status ="дитина"; else if(age <17) status ="школяр"; else if (age < 22) status = "студент"; else status = "службовець"; } get {return(age);} } /// <summary> ///стратегія: Write-only (Тільки запис) /// </summary> public int Salary { set {salary = value;} } }

Розглянемо тепер загальний синтаксис методів-властивостей. Хай name - це закрита властивість. Тоді для нього можна визначити відкритий метод-властивість (функцію), що повертає той же тип, що і поле name. Ім'я методу звичайно вибирається близьким до імені поля (наприклад, Name). Тіло властивості містить два методи - get і set, один з яких може бути опущений. Метод get повертає значення закритого поля, метод set - встановлює у момент виклику значення, використовуючи передаване йому значення, що зберігається в службовій змінній із стандартним ім'ям value. Оскільки get і set - це звичайні процедури мови, то програмно можна реалізувати скільки завгодно складні стратегії доступу. У нашому прикладі прізвище міняється, тільки якщо її значення рівне порожньому рядку і це означає, що прізвище персони жодного разу ще не задавалося. Статус персони перераховується автоматично при всякій зміні віку, явно змінювати його не можна. Ось приклад, що показує, як деякий клієнт створює і працює з полями персони:

Page 59: метуказлабраб ооп 2011укр

59

public void TestPersonProps() { Person pers1 = new Person(); pers1.Fam = "Петров"; pers1.Age = 21; pers1.Salary = 1000; Console.WriteLine ("Фам={0}, возраст={1}, статус={2}", pers1.Fam, pers1.Age, pers1.Status); pers1.Fam = "Іванов"; pers1.Age += 1; Console.WriteLine ("Фам={0}, возраст={1}, статус={2}", pers1.Fam, pers1 .Age, pers1.Status);

}//TestPersonProps

Індексатори

Властивості є окремим випадком методу класу з особливим синтаксисом. Ще одним окремим випадком є індексатор. Метод-індексатор є узагальненням методу-властивості. Він забезпечує доступ до закритого поля, що представляє масив. Об'єкти класу індексуються по цьому полю.

Синтаксично оголошення індексатора - таке ж, як і у разі властивостей, але методів get і set набувають аргументи по числу розмірності масиву, задаючого індекси елементу, значення якого читається або оновлюється. Важливим обмеженням є те, що у класу може бути тільки один індексатор і у цього індексатора стандартне ім'я this. Отже якщо серед полів класу є декілька масивів, то індексація об'єктів може бути виконана тільки по одному з них.

Приклад #1: Індексатори

using System; public class MyArray { private int[] mArray; public MyArray(int size) { mArray=new int[size]; } public int this[int index] // An Indexor { get if(index<0 || index>=mArray.Length) { return 0; } return mArray[index]; } set if(index<0 || index>=mArray.Length) { return; } mArray[index]=value; } } }

class TestMain { public static int Main() { MyArray ar=new MyArray(20); for(int i=-10;i<30;++i) { ar[i]= i; } for(int i=-10;i<30;++i) Console.WriteLine("Element: " + ar[i]); } return 0; } }

Page 60: метуказлабраб ооп 2011укр

60

Статичні поля і методи класу

Коли конструктор класу створює новий об'єкт, то в пам'яті створюється структура даних з полями, що визначаються класом. Але не всі поля відбиваються в структурі об'єкту. У класу можуть бути поля, пов'язані не з об'єктами, а з самим класом. Ці поля оголошуються як статичні з модифікатором static. Статичні поля доступні всім методам класу. Незалежно від того, який об'єкт викликав метод, використовуються одні і ті ж статичні поля, дозволяючи методу використовувати інформацію, створену іншими об'єктами класу. Статичні поля представляють загальний інформаційний пул для всіх об'єктів класу, дозволяючи витягувати і створювати загальну інформацію. Наприклад, у класу Person може бути статичне поле message, в якому кожен об'єкт може залишити повідомлення для інших об'єктів класу.

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

Конструктори класу

Конструктор - невід'ємний компонент класу. Немає класів без конструкторів. Конструктор є спеціальний метод класу, що дозволяє створювати об'єкти класу. Одна з синтаксичних особливостей цього методу в тому, що його ім'я повинне співпадати з ім'ям класу. Якщо програміст не визначає конструктор класу, то до класу автоматично додається конструктор за умовчанням - конструктор без аргументів. Відмітьте, що якщо програміст сам створює один або декілька конструкторів, то автоматичного додавання конструктора без аргументів не відбувається.

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

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

У класі можна оголосити статичний конструктор з атрибутом static. Він викликається автоматично - його не потрібно викликати стандартним чином. Такий конструктор може виконувати деяку попередню роботу, яку потрібно виконати один раз, наприклад, зв'язатися з базою даних, заповнити значення статичних полів класу, створити константи класу, виконати інші подібні дії

Деструктор класу

Якщо завдання створення об'єктів повністю покладається на програміста, то завдання видалення об'єктів, після того, як вони стали не потрібними, в Visual Studio .Net знята з програміста і покладена на відповідний інструментарій - складальник сміття. У класичному варіанті мови C++ деструктор так само необхідний класу, як і конструктор. У мові C# у класу може бути

деструктор, але він не займається видаленням об'єктів і не викликається нормальним чином в ході виконання програми. Так само, як і статичний конструктор, деструктор класу, якщо він є, викликається автоматично в процесі збірки сміття. Його роль - в звільненні ресурсів, наприклад, файлів, відкритих об'єктом.

Ім'я деструктора будується з імені класу з передуванням йому символа ~ (тильда). Як і у статичного конструктора, у деструктора не указується модифікатор доступу.

Спадкоємство

У об'єктно-орієнтованих системах визначено два основні типи відношень між класами. Перше відношення "клієнти і постачальники", називається часто клієнтським відношенням або відношенням вкладеності (вбудовування). Друге відношення "батьки і спадкоємці" називається відношенням спадкоємства [30].

Page 61: метуказлабраб ооп 2011укр

61

Визначення 1. Класи А і В знаходяться у відношенні "клієнт-постачальник", якщо одним з полів класу В є об'єкт класу А. Класс А називається постачальником класу В, клас В називається клієнтом класу А.

Визначення 2. Класи А і В знаходяться у відношенні "батько - спадкоємець", якщо при оголошенні класу В клас А вказаний як батьківський клас. Клас А називається батьком класу В, клас В називається спадкоємцем класу А.

Обидва відношення - спадкоємство і вкладеність - є транзитивними. Якщо В - клієнт А і C - клієнт В, то звідси витікає, що C - клієнт А. Якщо В - спадкоємець А і C - спадкоємець В, то звідси витікає, що C - спадкоємець А.

Визначення 1 і 2 задають прямих або безпосередніх клієнтів і постачальників, прямих батьків і спадкоємців. Внаслідок транзитивності необхідно ввести поняття рівня. Прямі клієнти і постачальники, прямі батьки і спадкоємці відносяться до відповідного рівня 1 (клієнти рівня 1, постачальники рівня 1 і так далі). Потім слідує рекурсивне визначення: прямий клієнт клієнта рівня k відноситься до рівня k+1.

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

Відмітимо, що ланцюжки вкладеності і спадкоємства можуть бути достатньо довгими. На практиці цілком можуть зустрічатися ланцюжки довжини 10. Наприклад, бібліотечні класи, складові системи Microsoft Office, повністю побудовані на відношенні вкладеності. При програмній роботі з об'єктами Word можна почати з об'єкту, задаючого застосування Word, і дістатися до об'єкту, задаючого окремий символ в деякому слові деякої пропозиції однієї з відкритих документів Word. Для вибору потрібного об'єкту можна задати такий ланцюжок: застосування Word - колекція документів - документ - область документа - колекція абзаців - абзац - колекція пропозицій - пропозиція - колекція слів - слово - колекція символів - символ. У цьому ланцюжку кожному поняттю відповідає клас бібліотеки Microsoft Office, де кожна пара класів, що є сусідами, зв'язана відношенням "постачальник-клієнт".

Класи бібліотеки FCL зв'язані як відношенням вкладеності, так і відношенням спадкоємства. Довгі ланцюжки спадкоємства достатньо характерні для класів цієї бібліотеки.

Відносини «є» і «має»

При проектуванні класів часто виникає питання, яке ж відношення між класами потрібно побудувати. Розглянемо зовсім простій приклад двох класів - Square і Rectangle, що описують квадрати і прямокутники. Напевно, зрозуміло, що ці класи слід зв'язати скоріше відношенням

спадкоємства, чим вкладеності; менш зрозумілим залишається питання, а якого з цих двох класів слід зробити батьківським. Ще один приклад двох класів - Car і Person, що описують автомобіль і персону. Якими відносинами з цими класами повинен бути зв'язаний клас Person_of_Car, що описує власника машини? Чи може він бути спадкоємцем обох класів? Знайти правильні відповіді на ці питання проектування класів допомагає розуміння того, що відношення "клієнт-

постачальник" задає відношення "має" ("has"), а відношення спадкоємства задає відношення "є"

("is а"). У разі класів Square і Rectangle зрозуміло, що кожен об'єкт квадрат "є" прямокутником, тому між цими класами має місце відношення спадкоємства, і батьківським класом є клас Rectangle, а клас Square є його нащадком.

У разі автомобілів, персон і власників авто також зрозуміло, що власник "має" автомобіль і "є" персоною. Тому клас Person_of_Car є клієнтом класу Car і спадкоємцем класу Person.

Page 62: метуказлабраб ооп 2011укр

62

Основи спадкоємства

C# підтримує спадкоємство, дозволяючи в оголошенні класу вбудовувати інший клас. Це реалізується за допомогою завдання базового класу при оголошенні похідного. Краще всього почати з прикладу. Розглянемо клас TwoDShape, в якому визначаються атрибути «узагальненої» двовимірної геометричної фігури (наприклад, квадрата, прямокутника, трикутника і т.д.)

class TwoDShape { public double width; public double height; public void showDim(){

Console.WriteLine(“Ширина і висота дорівнюють “ + width + “ і “ + height); } }

Клас TwoDShape можна використовувати як базового для класів, які описують специфічні типи двовимірних об'єктів. Наприклад, в наступній програмі клас TwoDShape використовується для виведення класу Triangle.

using System;

class TwoDShape { public double width; public double height; public void showDim(){ Console.WriteLine(“Ширина і висота рівні “ + width + “ і “ + height); } }

class Triangle : TwoDShape{ public string style; //Тип трикутника public double area(){ return width*height/2; } public void showStyle(){ Console.WriteLine(“Трикутник “+style); } } class Shapes{ public static void Main(){ Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.width = 4.0; t1.height = 4.0; t1.style = “рівнобедрений”;

t2.width = 8.0; t2.height = 12.0; t2.style = “прямокутний”;

Console.WriteLine(“Інформація про t1: ”); t1.showStyle(); t1.showDim(); Console.WriteLine(“Площа дорівнює: ” + t1.area());

Console.WriteLine();

Console.WriteLine(“Інформація про t2: ”); t2.showStyle(); t2.showDim(); Console.WriteLine(“Площа дорівнює: ” + t2.area()); } }

Page 63: метуказлабраб ооп 2011укр

63

Конструктори батьків і нащадків

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

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

Виклик конструктора батька відбувається не в тілі конструктора, а в заголовку, поки ще не створений об'єкт класу. Для виклику конструктора використовується ключове слово base, що іменує батьківський клас. Як це робиться, покажемо на прикладі конструкторів класу Derived:

public Derived() { public Derived(string name, int cred, int deb):base (name,cred) { debet = deb; }

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

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

Додавання методів і зміна методів батька

Нащадок може створити новий власний метод з ім'ям, відмінним від імен успадкованих методів. В цьому випадку ніяких особливостей немає. Ось приклад такого методу, що створюється в класі Derived:

public void DerivedMethod() { Console.WriteLine("Це метод класу Derived"); }

На відміну від незмінних полів класів-предків, клас-нащадок може змінювати успадковані ним методи. Якщо нащадок створює метод з ім'ям, співпадаючим з ім'ям методу предків, то можливі три ситуації:

Page 64: метуказлабраб ооп 2011укр

64

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

• перевизначення методу. Метод батька в цьому випадку повинен мати модифікатор virtual або abstract. При перевизначенні зберігається сигнатура і модифікатори доступу успадкованого методу;

• утаєння методу. Якщо батьківський метод не є віртуальним або абстрактним, то нащадок

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

Метод нащадка, що приховує метод батька, слід супроводжувати модифікатором new, вказуючим на новий метод.

Віртуальні методи

Розглянемо три механізми, що забезпечують поліморфізм [30]. Під поліморфізмом в ООП розуміють здатність одного і того ж програмного тексту x.M виконуватися по-різному, залежно від того, з яким об'єктом пов'язана суть x. Поліморфізм гарантує, що метод M, що викликається, належатиме класу об'єкту, пов'язаному з сутністю x. У основі поліморфізму, характерного для сімейства класів, лежать три механізми:

• одностороннє привласнення об'єктів усередині сімейства класів; сутність, базовим класом якої є клас предка, можна пов'язати з об'єктом будь-якого з нащадків;

• перевизначення нащадком методу, успадкованого від батька. Завдяки перевизначенню, в сімействі класів існує сукупність поліморфних методів з одним ім'ям і сигнатурою;

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

У сукупності це і називається поліморфізмом сімейства класів. Поліморфізм реалізується через механізм віртуальних функцій (дивися Вправу 2).

Абстрактні класи

Із спадкоємством тісно пов'язаний ще один важливий механізм проектування сімейства класів - механізм абстрактних класів. Клас називається абстрактним, якщо він має хоч би один абстрактний метод. Метод називається абстрактним, якщо при визначенні методу задана його сигнатура, але не задана реалізація методу. Оголошення абстрактних методів і абстрактних класів повинне супроводжуватися модифікатором abstract. Оскільки абстрактні класи не є повністю визначеними класами, то не можна створювати об'єкти абстрактних класів. Абстрактні класи можуть мати нащадків, що частково або повністю реалізовують абстрактні методи батьківського класу. Абстрактний метод найчастіше розглядається як віртуальний метод, що перевизначається нащадком, тому до них застосовується стратегія динамічного скріплення. Далі дивися приклад #2 Вправи 2.

Page 65: метуказлабраб ооп 2011укр

65

Лабораторна робота №6. Перевантаження операцій в C#.

Мета роботи: засвоїти основи перевизначення операцій в мові C#, набути практичних навичок розробки класів з перевантаженими операціями.

Варіанти завдання.

Варіант 1. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“+” - додати елемент в множину (типу char + set); “+” - об'єднання множин; “==” - перевірка множин на рівність.

Варіант 2.. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“-” - видалити елемент з множини (типу set-char); “*” - перетин множин; “<” - порівняння множин .

Варіант 3. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“-” - видалити елемент з множини(типу set-char); “>”- перевірка на підмножину; “!=” - перевірка множин на нерівність.

Варіант 4. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“+” - додати елемент в множину (типу set + char); “*” - перетин множин; “int ()” - потужність множини.

Варіант 5. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“()” - конструктор множини (у стилі конструктора Паскаля); “+” - об'єднання множин; “<=” - порівняння множин .

Варіант 6. Абстрактний тип даних (АТД ) – множина з елементами типу char. Додатково перенавантажувати наступні операції:

“>” -проверка на приналежність (char in set Паскаля); “*” -перетин множин; “<” -проверка на підмножину.

Варіант 7. Абстрактний тип даних (АТД ) – однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“+” – об’єднати списки (list+list); “--” - видалити елемент з початку (типу --list); “==” перевірка на рівність.

Варіант 8. Абстрактний тип даних (АТД ) – однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“+” - додати елемент в початок (char+list); “--” - видалити елемент з початку(типу --list);

Page 66: метуказлабраб ооп 2011укр

66

“==” перевірка на рівність.

Варіант 9. Абстрактний тип даних (АТД ) – однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“+” -добавить елемент в кінець(list+char); “--” -удалить елемент з кінця(типу list--); “!=” перевірка на нерівність.

Варіант 10.. Абстрактний тип даних (АТД ) – однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“[]” -доступ до елементу в заданій позиції, наприклад: int i; char c; list L; c=L[i]; “+” - об'єднати два списки; “==” перевірка на рівність.

Варіант 11. АДТ-однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“[]” -доступ до елементу в заданій позиції, наприклад: int i; char c; list L; c=L[i]; “+” - об'єднати два списки; “!=” перевірка на нерівність.

Варіант 12. Абстрактний тип даних (АТД ) – однонаправлений список з елементами типу char. Додатково перенавантажувати наступні операції:

“()” - видалити елемент в заданій позиції, наприклад : int i; list L; L[i]; “()” - додати елемент в задану позицію, наприклад : int i; char c; list L; L[с,i]; “!=” перевірка на нерівність.

Варіант 13. Абстрактний тип даних (АТД ) – стек. Додатково перенавантажувати наступні операції:

“+” додати елемент в стек; “—“ витягнути елемент із стека; bool() - перевірка чи порожній стек?

Варіант 14. Абстрактний тип даних (АТД ) – черга. Додатково перенавантажувати наступні операції:

“+” додати елемент ; “—“ витягнути елемент ; bool() - перевірка чи порожня черга?

Варіант 15. Абстрактний тип даних (АТД ) – одновимірний масив (вектор) дійсних чисел. Додатково перенавантажувати наступні операції:

“+” додавання векторів (а[i]+b[i] для всіх i);

Page 67: метуказлабраб ооп 2011укр

67

“[]” доступ по індексу; “+” додати число до вектора (double+vector).

Варіант 16. Абстрактний тип даних (АТД ) – одновимірний масив (вектор) дійсних чисел. Додатково перенавантажувати наступні операції:

“-” віднімання векторів(а[i]-b[i] для всіх i); “[]” доступ по індексу; “-” відняти з вектора число(vector-double).

Варіант 17. Абстрактний тип даних (АТД ) – одновимірний масив (вектор) дійсних чисел. Додатково перенавантажувати наступні операції:

“*” множення векторів(а[i]*b[i] для всіх i); “[]” доступ по індексу; “*” помножити вектор на число (vector*double).

Варіант 18. Абстрактний тип даних (АТД ) – одновимірний масив(вектор) дійсних чисел. Додатково перенавантажувати наступні операції:

“int()” розмір вектора; “()” встановити новий розмір; “-” відняти з вектора число(vector-double); “[]” доступ по індексу;

Варіант 19. Абстрактний тип даних (АТД ) – одновимірний масив(вектор) дійсних чисел. Додатково перенавантажувати наступні операції:

“=” привласнити всім елементам вектора значення(vector=double); “[]” доступ по індексу; “==” перевірка на рівність; “!=” перевірка на нерівність;

Варіант 20. Абстрактний тип даних (АТД ) – двомірний масив (матриця) дійсних чисел. Додатково перенавантажувати наступні операції:

“()” доступ по індексу; “*” множення матриць; “*” множення матриці на число; “*” множення числа на матрицю.

Варіант 21. Абстрактний тип даних (АТД ) – двомірний масив(матриця) дійсних чисел. Додатково перенавантажувати наступні операції:

“()” доступ по індексу; “-” різниця матриць; “-” відняти з матриці число; “==” перевірка матриць на рівність.

Варіант 22. Абстрактний тип даних (АТД ) – двомірний масив (матриця) дійсних чисел. Додатково перенавантажувати наступні операції:

“()” доступ по індексу; “=” привласнити всім елементам матриці значення(matr=double); “+” додавання матриць; “+” скласти матрицю з числом(matr+double).

Хід роботи.

1. Виконати Вправу.

Page 68: метуказлабраб ооп 2011укр

68

2. Виконати завдання згідно своєму варіанту.

Вправа. Клас Fraction раціональних чисел (дробів).

Розглянемо клас Fraction раціональних чисел (дробів) з перевантаженими операціями “+”, “-”, “*”, “/” ++ і – (у префіксній і інфіксній формах), операції унарний мінус [29].

public struct Fraction { private long mNumerator; //чисельник private long mDenominator; //знаменник public Fraction(long aNumerator, long aDenominator) { // Cancel the fraction and make the denominator positive long gcd = GreatestCommonDivisor( aNumerator, aDenominator); mNumerator = aNumerator / gcd; mDenominator = aDenominator / gcd; if (mDenominator < 0) { mNumerator = -mNumerator; mDenominator = -mDenominator; } } private static long GreatestCommonDivisor( long aNumber1, long aNumber2) { aNumber1 = Math.Abs(aNumber1); aNumber2 = Math.Abs(aNumber2); while (aNumber1 > 0) { long newNumber1 = aNumber2 % aNumber1; aNumber2 = aNumber1; aNumber1 = newNumber1; } return aNumber2; } public static Fraction operator +(Fraction aF1, Fraction aF2) { long num = aF1.mNumerator*aF2.mDenominator + aF2.mNumerator*aF1.mDenominator; long denom = aF1.mDenominator*aF2.mDenominator; return new Fraction(num, denom); } public static Fraction operator -(Fraction aF1, Fraction aF2) { long num = aF1.mNumerator*aF2.mDenominator - aF2.mNumerator*aF1.mDenominator; long denom = aF1.mDenominator*aF2.mDenominator; return new Fraction(num, denom); } public static Fraction operator *(Fraction aF1, Fraction aF2) { long num = aF1.mNumerator*aF2.mNumerator; long denom = aF1.mDenominator*aF2.mDenominator; return new Fraction(num, denom); } public static Fraction operator /(Fraction aF1, Fraction aF2)

Page 69: метуказлабраб ооп 2011укр

69

{ long num = aF1.mNumerator*aF2.mDenominator; long denom = aF1.mDenominator*aF2.mNumerator; return new Fraction(num, denom); } // Unary minus operator public static Fraction operator -(Fraction aFrac) { long num = -aFrac.mNumerator; long denom = aFrac.mDenominator; return new Fraction(num, denom); } // Explicit conversion to double operator public static explicit operator double(Fraction aFrac) { return (double) aFrac.mNumerator / aFrac.mDenominator; } // Operator ++ (the same for prefix and postfix form) public static Fraction operator ++(Fraction aFrac) { long num = aFrac.mNumerator + aFrac.mDenominator; long denom = aFrac.mDenominator; return new Fraction(num, denom); } // Operator -- (the same for prefix and postfix form) public static Fraction operator --(Fraction aFrac) { long num = aFrac.mNumerator - aFrac.mDenominator; long denom = aFrac.mDenominator; return new Fraction(num, denom); } public static bool operator true(Fraction aFraction) { return aFraction.mNumerator != 0; } public static bool operator false(Fraction aFraction) { return aFraction.mNumerator == 0; } public static implicit operator Fraction(double aValue) { double num = aValue; long denom = 1; while (num - Math.Floor(num) > 0) { num = num * 10; denom = denom * 10; } return new Fraction((long)num, denom); } public override string ToString() { if (mDenominator != 0) { return String.Format("{0}/{1}", mNumerator, mDenominator); }

Page 70: метуказлабраб ооп 2011укр

70

else { return ("NAN"); // not а number } } } class FractionsTest { static void Main() { Fraction f1 = (double)1/4; Console.WriteLine("f1 = {0}", f1); Fraction f2 = (double)7/10; Console.WriteLine("f2 = {0}", f2); Console.WriteLine("-f1 = {0}", -f1); Console.WriteLine("f1 + f2 = {0}", f1 + f2); Console.WriteLine("f1 - f2 = {0}", f1 - f2); Console.WriteLine("f1 * f2 = {0}", f1 * f2); Console.WriteLine("f1 / f2 = {0}", f1 / f2); Console.WriteLine("f1 / f2 as double = {0}", (double)(f1 / f2)); Console.WriteLine( "-(f1+f2)*(f1-f2/f1) = {0}", -(f1+f2)*(f1-f2/f1)); }

}

Методичні вказівки та теоретичні відомості.

Мова C# дозволяє визначити значення операції щодо створюваного класу. Цей процес називається перевантаженням операцій. Перенавантажуючи операцію, ви розширюєте її використання для класу.

Основи перевантаження операцій

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

Існує дві форми методів operator: одна використовується для унарних операцій, а інша – для бінарних.

//загальний формат перевантаження для унарної операції public static тип_возврата operator op( тип_параметра операнд){ //тіло_метода }

// загальний формат перевантаження для бінарної операції public static тип_возврата operator op( тип_параметра1 операнд1, тип_параметра2 операнд2) { //тіло_метода }

Тут елемент op – це операція (наприклад “+” або “/”), яка перевантажується. Елемент тип_возврата – це тип значення, що повертається при виконанні заданої операції. Для унарних операцій тип операнда повинен співпадати з класом, для якого визначена операція. Що стосується бінарних операцій, то тип хоч би одного операнда повинен співпадати з відповідним класом. Таким чином, C#-операции не можна перенавантажувати для класів, не створених вами. Наприклад, ви не можете перенавантажувати операцію “+” для типів int або string.

Page 71: метуказлабраб ооп 2011укр

71

Перевантаження бінарних операцій

Приклад #1: Operator “+” overloading

using System; public class Integer { public int mValue; // Bad Idea for public data member public Integer(int value) { mValue=value; } public static Integer operator + (Integer x,Integer у) Integer sum=new Integer(0); sum.mValue=x.mValue + у.mValue; return sum; } }

class TestMain { public static int Main() { Integer y=new Integer(10); Integer z=new Integer(20); Integer w; w= y+z+y+z; Console.WriteLine("Integer:"+w.mValue); return 0; } }

Перевантаження унарних операцій

Приклад #2: Overload operator - with unary

using System; public class Integer { private int mValue; public Integer(int value) { mValue=value; } public static Integer operator + (Integer x,Integer у) Integer sum=new Integer(0); sum.mValue=x.mValue + у.mValue; return sum; } override public String ToString() return mValue.ToString(); } public static Integer operator - (Integer x,Integer у) Integer sum=new Integer(0); sum.mValue=x.mValue - у.mValue; return sum; } public static Integer operator - (Integer x) Integer ret=new Integer(0); ret.mValue = -х.mValue; return ret;

Page 72: метуказлабраб ооп 2011укр

72

} } class TestMain { public static int Main() { Integer y=new Integer(10); Integer z=new Integer(20); Integer w=new Integer(15); Integer u; u= -y+z-w+y+z; // Minus + Plus Expression Console.WriteLine("Integer:"+u); return 0; } }

Лабораторна робота №7. Делегати і події.

Мета роботи: засвоїти теоретичні основи визначення і використання делегатів і подій в мові C#, набути практичних навичок розробки програм з функціональним типом даних.

Варіанти завдання.

1. Розробити клас для обчислення визначених інтегралів за формулою трапецій з використанням делегатів.

2. Розробити клас для обчислення визначених інтегралів за формулою Симпсона з використанням делегатів.

3. Розробити клас для обчислення визначених інтегралів за формулою Гауса з використанням делегатів.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати завдання згідно своєму варіанту.

Вправа 1.

Вивчити і реалізувати приклади #1 - #5, в яких використовуються делегати.

Приклад #1: Delegate

using System; public delegate void Fun(); // Create а delegate type called Fun class TestMain { private static void Test() // static fun { Console.WriteLine("Hello Test"); } public static void Main() { Fun x=new Fun(Test); // Create Delegate Instance x(); // Call Delegate }

Page 73: метуказлабраб ооп 2011укр

73

}

Приклад #2: Delegate (unicast Delegate)

using System; public delegate int Fun(int x,int у); // Create а delegate type called Fun class TestMain { private static int Sum(int x,int у) { return x+y; } public static void Main() { Fun x=new Fun(Sum); // Create Delegate Instance Console.WriteLine("Sum="+ x(10,20)); } }

Приклад #3: Multicasting + Delegate Operations

using System; public delegate void Fun(int x,int у); // void return class TestMain { private static void Sum(int x,int у) Console.WriteLine("Called Sum "+x+","+y); } private static void Prod(int x,int у) Console.WriteLine("Called Product "+x+","+y); } public static void Main() { Fun x=new Fun(Sum); Fun y=new Fun(Prod); x+=y; x(20,30); x+=x; x(10,20); x-=y; x-=y; x-=y; x(1,1); } } Приклад #4: Object Methods

using System; public delegate void Fun(int x,int у); // void return class Car { public void Start(int а,int b) { Console.WriteLine("Start Called"); } public void Stop(int а,int b) { Console.WriteLine("Stop Called"); } } class TestMain { static void Main() { Car a=new Car(); Fun f=new Fun(а.Start); // Object Method! f += new Fun(а.Stop); f(10,20); } }

Page 74: метуказлабраб ооп 2011укр

74

Приклад #5: Delegate to print output

using System; delegate void OutputFun(int value); // Multicasting delegate class PrimeCalc { // Check if Prime private bool IsPrime(int val) { if(val<=1) { return false; } for(int k=2;k<=val-1;++k) { if(val % k==0) { return false; } } return true; } // Find All primes <= than n public void FindPrimes(int n,OutputFun output) { for(int i=2;i<=n;++i) { if(IsPrime(i)==true) { output(i); } } } } class TestMain { public static void PrintPrime(int item) Console.WriteLine("Prime: "+item); } public static void Main() { PrimeCalc x=new PrimeCalc(); OutputFun fun=new OutputFun(TestMain.PrintPrime); x.FindPrimes(100,fun); } }

Вправа 2.

Вивчити і реалізувати приклад #6, в якому використовуються події і делегати.

Приклад #6:Event Handling

using System;

delegate void Action(); // First Create а delegate

class AlarmClock

{

public event Action Alarm; // Public Alarm Event

public void Start(int count)

{

for(int i=0;i<count;++i) { } // Delay loop

if(Alarm!=null) { Alarm(); }

}

}

class TestMain

Page 75: метуказлабраб ооп 2011укр

75

{

public static void WakeUp()

{

Console.WriteLine("Wake Up Now....");

}

public static void Main()

{

AlarmClock clk=new AlarmClock();

clk.Alarm += new Action(WakeUp);

clk.Start(1000000000);

}

}

Методичні вказівки і теоретичні відомості.

Делегати

Почнемо з визначення терміну делегат (delegate). Делегат – це об'єкт, який може посилатися на метод. Таким чином, створюючи делегата, ви, по суті, створюєте об'єкт, який може містити посилання на метод. Більш того, цей метод можна викликати за допомогою відповідного посилання. Таким чином, делегат може викликати метод, на який він посилається.

Делегат в C# в деякому роді аналогічний покажчику на функцію в C/C++.

Делегат задає визначення функціонального типу (класу) даних. Екземплярами класу є функції. Опис делегата в мові C# є описом ще одного окремого випадку класу. Кожен делегат описує множину функцій із заданою сигнатурою. Кожна функція (метод), сигнатура якої співпадає з сигнатурою делегата, може розглядатися як екземпляр класу, заданого делегатом. Синтаксис оголошення делегата має наступний вигляд:

[<специфікатор доступу>] delegate <тип результату > <ім'я класу> (<список аргументів>);

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

Специфікатор доступу може бути, як завжди, опущений. Де слід розміщувати оголошення делегата? Як і у всякого класу, є дві можливості:

• безпосередньо у просторі імен, разом з оголошеннями інших класів, структур, інтерфейсів; • усередині іншого класу, разом з оголошеннями методів і властивостей. Таке оголошення

розглядається як оголошення вкладеного класу.

Так само, як і інтерфейси C#, делегати не задають реалізації. Фактично між деякими класами і делегатом полягає контракт на реалізацію делегата. Класи, згодні, з контрактом повинні оголосити у себе статичні або динамічні функції, сигнатура яких співпадає з сигнатурою делегата. Якщо контракт виконується, то можна створити екземпляри делегата, привласнивши їм як значення функції, що задовольняють контракту. Відмітьте, контракт є жорстким: не допускається ситуація, при якій у делегата тип параметра, - object, а у екземпляра відповідний параметр має тип, узгоджений з object, наприклад, int.

Page 76: метуказлабраб ооп 2011укр

76

Одне з найбільш важливих застосувань делегатів пов'язане з функціями вищих порядків [30]. Функцією вищого порядку називається така функція (метод) класу, у якої один або декілька аргументів належать до функціонального типу. Без цих функцій в програмуванні обійтися досить важко. Класичним прикладом є функція обчислення інтеграла, у якої один з аргументів задає підінтегральну функцію. Іншим прикладом може служити функція, що сортує об'єкти. Аргументом її є функція Compare, що порівнює два об'єкти. Залежно від того, яка функція порівняння буде передана на вхід функції сортування, об'єкти сортуватимуться по-різному, наприклад, по імені, або по ключу, або по декількох полях. Використання функції вищого порядку приведене в Прикладі #5 Вправи 1.

Операції над делегатами. Клас Delegate.

При визначенні функціонального типу, наприклад:

public delegate int FType(int X);

змінна FType належить класу Delegate. Чому ж її не можна оголосити звичним чином? Справа не тільки в синтаксичних особливостях цього класу. Річ у тому, що клас Delegate є абстрактним класом. Ось його оголошення:

public abstract class Delegate: ICloneable, ISerializable

Для абстрактних класів реалізація не визначена, і це означає, що не можна створювати екземпляри класу. Клас Delegate слугує базовим класом для класів-спадкоємців. Але створювати спадкоємців можуть тільки компілятори і системні програми – цього не можна зробити в програмі на C#. Саме тому введено ключове слово delegate, яке побічно дозволяє працювати з класом Delegate, створюючи вже не абстрактний, а реальний клас. Відмітьте, при цьому всі динамічні і статичні методи класу Delegate стають доступними програмістові.

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

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

передачею (multicasting).

У чому суть комбінування делегатів? Вона полягає в наступному. До екземпляра делегата

дозволяється по черзі приєднувати інші екземпляри делегата того ж типу (за допомогою методу Combine() або операції “+=”). Оскільки кожен екземпляр зберігає посилання на функцію, то в результаті створюється список посилань. Цей список називається списком викликів (invocation

list). Коли викликається екземпляр, що має список виклику, то по черзі, в порядку приєднання, починають викликатися і виконуватися функції, задані посиланнями. Так один виклик породжує виконання списку робіт (дивися приклад #3 Вправи 1).

Зрозуміло, що, якщо є операція приєднання делегатів, то повинна бути і зворотна операція, що дозволяє видаляти делегатів із списку. Вона здійснюється за допомогою методу Remove() або операції “-=”.

Розглянемо основні методи і властивості класу Delegate. Почнемо з двох статичних методів - Combine і Remove. Перший з них приєднує екземпляри делегата до списку, другий - видаляє із списку. Обидва методи мають схожий синтаксис:

Page 77: метуказлабраб ооп 2011укр

77

Combine(del1, del2) Remove(del1, del2)

Аргументи del1 і del2 повинні бути одного функціонального класу. При додаванні del2 в список, в якому del2 вже присутній, буде доданий другий екземпляр. При спробі видалення del2 із списку, в якому del2 немає, Remove благополучно завершить роботу, не видаючи повідомлення про помилку.

Клас Delegate відноситься до незмінних класів, тому обидва методи повертають посилання на нового делегата. Посилання, що повертається, належить батьківському класу Delegate, тому його необхідно явно перетворити до потрібного типу, якому належать del1 і del2. Звичайне використання цих методів має вигляд:

del1 = (<type>) Combine(del1, del2); del1 = (<type>) Remove(del1, del2);

Метод GetInvocationList є динамічним методом класу - він повертає список викликів екземпляра, що викликав метод. Потім можна влаштувати цикл foreach, по черзі отримуючи елементи списку.

Події

На основі делегатів побудований ще один важливий засіб C#: подія (event). Подія – це, по суті, автоматичне повідомлення про виконання деякої дії. Події працюють таким чином. Об'єкт, якому необхідна інформація про деяку подію, реєструє обробник для цієї події. Коли очікувана подія відбувається, викликаються всі зареєстровані обробники. Обробники подій представляються делегатами.

Події – це члени класу, які оголошуються з використанням ключового слова event. Найбільш поширена форма оголошення події має наступний вигляд:

event подієвий_делегат об'єкт;

Тут елемент подієвий_делегат означає ім'я делегата, використовуваного для підтримки оголошеної події, а елемент об'єкт – це ім'я створюваного подієвого об'єкту.

Оголошення події - це двохетапний процес:

• Спочатку оголошується делегат - функціональний клас, що задає сигнатуру. Як наголошувалося при розгляді делегатів, оголошення делегата може бути поміщене в деякий клас, наприклад, клас Sender. Але, найчастіше, це оголошення знаходиться поза класом в просторі імен. Оскільки одна і та ж сигнатура може бути у різних подій, то для них досить мати одного делегата. Для деяких подій можна використовувати стандартних делегатів, вбудованих в каркас. Тоді достатньо знати тільки їх імена.

• Якщо делегат визначений, то в класі Sender, що створює події, досить оголосити подію як екземпляр відповідного делегата. Це робиться точно так, як і при оголошенні функціональних екземплярів делегата. Виключенням є додавання службового слова event. Формальний синтаксис оголошення такий:

[атрибути] [модифікатори]event [тип, заданий делегатом] [ім'я події]

Найчастіше, атрибути не задаються, а модифікатором є модифікатор доступу - public. Приведемо приклад оголошення делегата і події, що представляє екземпляр цього делегата:

namespace Events { public delegate void FireEventHandler(object Sender int time, int build);

Page 78: метуказлабраб ооп 2011укр

78

public class TownWithEvents { public event FireEventHandler FireEvent; ... }//TownWithEvents ... }//namespace Events

Тут делегат FireEventHandler описує клас подій, сигнатура яких містить три аргументи. Подія FireEvent в класі TownWithEvents є екземпляром класу, заданого делегатом.

Як генеруються події

Причини виникнення події можуть бути різними. Тому цілком імовірно, що одна і та ж подія “запалюватиметься” [30] в різних методах класу в той момент, коли виникне одна з причин появи події. Оскільки дії по включенню можуть повторюватися, корисно до складу методів класу додати захищену процедуру, що генерує подію. Навіть якщо подія “запалюється” тільки в одній точці, написання такої процедури вважається ознакою хорошого стилю. Цій процедурі зазвичай дається ім'я, що починається із слова On, після якого слідує ім'я події. Називатимемо таку процедуру On-процедурою. Вона проста і складається з виклику оголошеної події, включеної в тест, який перевіряє перед викликом, а чи є хоч один обробник події, здатний прийняти відповідне повідомлення. Якщо таких немає, то нічого включати подію. Розглянемо приклад:

protected virtual void OnFireEvent(int time, int build) { if (FireEvent!=null) FireEvent(this,time, build); }

Зверніть увагу: ті, хто приймає повідомлення про подію, повинні наперед приєднати обробники подій до об'єкту FireEvent, задаючого подію. Приєднання обробників повинне передувати запаленню події. При такому нормальному ході речей, знайдеться хоч би один слухач повідомлення про подію - отже, FireEvent не буде рівне null.

Продемонструємо використання простої події.

using System;

delegate void MyEventHandler(); // Оголошуємо делегат для події

class MyEvent {

public event MyEventHandler SomeEvent;

//Цей метод викликається для генерування події

public void OnSomeEvent(){

if(SomeEvent!=null) { SomeEvent (); }

}

}

class EventDemo{

static void handler(){ // Обробник події

Console.WriteLine("Відбулася подія.");

}

public static void Main(){

MyEvent evt=new MyEvent();

// Додаємо метод handler() у список обробників події

Page 79: метуказлабраб ооп 2011укр

79

evt.SomeEvent += new MyEventHandler(handler);

// Генеруємо подію

evt.OnSomeEvent();

}

}

Лабораторна робота №8. Використання елементів Windows Forms і діалогових

вікон.

Мета роботи: засвоїти основні властивості і методи елементів Windows Forms для створення призначеного для користувача інтерфейсу, набути практичних навичок розробки графічних застосувань з розвиненим інтерфейсом користувача.

Варіанти завдання.

Варіант 1.

Написати застосування Windows, яке за заданими у файлі початковими даними будує графік або стовпчикову діаграму. Етапи виконання роботи: 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Begin (підпункти Input data, Choose), Line, Bar, About, Quit Пункти Line і Bar заборонені. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) По Input data з файлу читаються початкові дані (файл сформувати самостійно). Видається повідомлення про результат. 4) По Choose відкривається діалогове вікно вигляду: -----------------------------------------------------¬ | Color: | | --1---------T¬ --2-----------¬ ---------¬ | | +-----------+| | | | O K | | | +-----------+| | O Line | L========- | | +-----------+| | | ---------¬ | | +-----------+| | O Bar | | Cancel | | | L-----------+- L-------------- L========- | L----------------------------------------------------- де 1 - вікно-список для вибору кольору графіка, 2 - група кнопок типа Radio Button OK, Cancel - кнопки типа Button 5) Забезпечується можливість введення кольору і вибору режиму за допомогою кнопок 2: побудова графіка (Line) або стовпчикової діаграми (Bar). Після вибору активізується відповідний пункт меню. 6) По Line або Bar в головному вікні застосування вибраним кольором будується графік або діаграма. Вікно повинне містити заголовок, найменування і градацію осей. Зображення повинне займати все вікно. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 2.

Написати застосування Windows, яке за заданими у файлі початковими даними будує графік або стовпчикову діаграму. Етапи виконання роботи: 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Begin (підпункти Input і Choose) Color Draw About Quit Пункт Draw заборонений. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника.

Page 80: метуказлабраб ооп 2011укр

80

3) По Input з файлу читаються початкові дані (файл сформувати самостійно). Видається повідомлення про результат. 4) По Choose відкривається діалогове вікно вигляду: -----------------------------------¬ | --1-----------¬ ---------¬ | | | | | O K | | | | O Line | L========- | | | | ---------¬ | | | O Bar | | Cancel | | | L-------------- L========- | L----------------------------------- де 1 - група кнопок типа Radio Button, OK, Cancel - кнопки типа Button 5) Забезпечується можливість вибору режиму за допомогою кнопок 1: побудова графіка (Line) або стовпчикової діаграми (Bar). 6) По Color відкривається діалогове вікно для введення RGB-складових кольори графіка (діаграми): -----------------------------------------------¬ | -1---------------¬ ---------¬ | | L----------------- Red | O K | | | -2---------------¬ L========- | | L----------------- Green ---------¬ | | -3---------------¬ | Cancel | | | L----------------- Blue L========- | L----------------------------------------------- де 1,2,3 - вікно-редактор (Edit Box). Після вибору активізується пункт меню Draw. 7) По Draw в головному вікні застосування вибраним кольором будується графік або діаграма. Вікно повинне містити заголовок, найменування і градацію осей. Зображення повинне займати все вікно. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 3.

Написати застосування Windows, яке за заданими у файлі початковими даними будує графік, стовпчикову або кругову діаграму. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Prepare Draw Exit |Input data| |Choose | По Exit застосування завершується. 3) По Input data з файлу читаються початкові дані (файл сформувати самостійно). Видається повідомлення про результат. 4) По Choose відкривається діалогове вікно вигляду: -----------------------------------¬ | --1-----------¬ ---------¬ | | | | | O K | | | | O Bar | L========- | | | O Pie | ---------¬ | | | O Line | | Cancel | | | L-------------- L========- | L----------------------------------- де 1 - група кнопок типа Radio Button, OK, Cancel - кнопки типа Button 5) Забезпечується можливість вибору режиму за допомогою кнопок 1: побудова графіка (Line), стовпчикової діаграми (Bar) або кругової діаграми (Pie). 6) По Draw в головному вікні застосування будується графік або діаграма. Вікно повинне містити заголовок, найменування і градацію осей. Зображення повинне займати все вікно. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 4.

Написати застосування Windows, яке будує графіки чотирьох заданих функцій. Етапи виконання роботи.

Page 81: метуказлабраб ооп 2011укр

81

1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Chart About Quit |Build | |Clear | По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) По Build відкривається діалогове вікно вигляду: ----------------------------------------------------¬ | Color: Chart: | | --1---------T¬ --2---------T¬ ---------¬ | | +-----------+| +sin(x) +| | O K | | | +-----------+| +sin(x+pi/4)+| L========- | | +-----------+| +cos(x) +| ---------¬ | | +-----------+| +cos(x-pi/4)+| | Cancel | | | L-----------+- L-----------+- L========- | L---------------------------------------------------- де 1 - вікно-список для вибору кольору графіка, 2 - вікно-список для вибору виду графіка OK, Cancel - кнопки типа Button. 4) Забезпечується можливість вибору кольору і виду графіка. Після натиснення кнопки ОК в головному вікні застосування будується графік вибраної функції на інтервалі від -pi/2 до +pi/2. Вікно повинне містити заголовок, найменування і градацію осей. Зображення повинне займати все вікно. Зображення повинне масштабуватися при зміні розмірів вікна. 5) По Clear головне вікно очищається. Варіант 5.

Написати застосування Windows, яке будує графіки чотирьох заданих функцій. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, гр., вар. 2) Створити меню вигляду: Chart Clear About Quit |Choose | |Build | По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) З кожним пунктом меню зв'язати "гарячі клавіші". 4) По Choose відкривається діалогове вікно вигляду: ----------------------------------------------------¬ | Limits: Chart: | | -1------¬ --3---------T¬ ---------¬ | | | | from +sin(x) +| | O K | | | L-------- +sin(x+pi/4)+| L========- | | -2------¬ +cos(x) +| ---------¬ | | | | to +cos(x-pi/4)+| | Cancel | | | L-------- L-----------+- L========- | L---------------------------------------------------- де 1,2 - вікна-редактори (Edit Box) для введення діапазону значень аргументу 3 - вікно-список (Combo Box) для вибору виду графіка OK, Cancel - кнопки типа Button. 5) Забезпечується можливість вибору діапазону і виду графіка. 6) По Build в головному вікні застосування будується графік вибраної функції на введеному інтервалі. Вікно повинне містити заголовок, найменування і градацію осей. Зображення повинне займати все вікно. Зображення повинне масштабуватися при зміні розмірів вікна. 7) По Clear головне вікно очищається. Варіант 6.

Написати застосування Windows, яке виконує анімацію бітового образу. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Begin Animate Stop About Quit |Show picture| |Choose |

Page 82: метуказлабраб ооп 2011укр

82

По Quit застосування завершується. По About відкривається вікно з інформацією про розробника.

3) По Show picture в центрі екрану малюється об'єкт, що складається з декількох графічних примітивів. Він запам'ятовується у вигляді бітового образу.

4) По Choose відкривається діалогове вікно вигляду: -----------------------------------------------------¬ | Speed: Direction: | | --1---------¬ --2-----------¬ ---------¬ | | L------------ | | | O K | | | | O Up-Down | L========- | | | | ---------¬ | | | O Left-Right| | Cancel | | | L-------------- L========- | L-----------------------------------------------------

де 1 - окно-pедактоp (Edit Box) для введення швидкості руху об'єкту 2 - група кнопок типу Radio Button для вибору напряму руху OK, Cancel - кнопки типу Button. 5) По Animate об'єкт починає переміщатися у вибраному напрямі до краю вікна і назад із заданою швидкістю, по Stop - припиняє рух. Варіант 7.

Написати застосування Windows, яке виконує анімацію бітового образу. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Begin Animate Stop About Quit |Show picture| |Choose | По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) По Show picture в центрі екрану малюється об'єкт, що складається з декількох графічних примітивів. Він запам'ятовується у вигляді бітового образу. 4) По Choose відкривається діалогове вікно вигляду: -----------------------------------------------------¬ | From Speed: | | --1--¬ -2---¬ --5----------T¬ ---------¬ | | L----- L----- +------------+| | O K | | | +------------+| L========- | | To: +------------+| ---------¬ | | --3--¬ -4---¬ +------------+| | Cancel | | | L----- L----- L------------+- L========- | L----------------------------------------------------- де 1,2,3,4 - вікна-pедактоpи (Edit Box) для введення X і Y координат початкового і кінцевого положення об'єкту 5 - вікно-список для введення швидкості руху об'єкту OK, Cancel - кнопки типу Button. 5) По Animate об'єкт починає переміщатися між вибраними точками із заданою швидкістю, по Stop - припиняє рух. Варіант 8.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: List Best About Quit Пункт Best заборонений. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List відкривається діалогове вікно, що містить: - вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф;

Page 83: метуказлабраб ооп 2011укр

83

- групу з трьох кнопок Radio Button: Overall, Performance, Service; - Arrange, OK, Cancel - кнопки типу Button. По натисненню Arrange список упорядковується по убуванню відміченої за допомогою одної з радіо-кнопок характеристики. Пункт меню Best активізується. 5) По Best відкривається вікно повідомлень, що містить інформацію про комп'ютер що володіє якнайкращою характеристикою, вибраною в діалоговому вікні. Варіант 9.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Work (пункти підменю List, Best, About), Exit Пункт Best заборонений. По Exit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List відкривається діалогове вікно, що містить: - вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з трьох кнопок Radio Button: Performance, Price, Hard drive; - Arrange,OK, Cancel - кнопки типу Button;. По натисненню Arrange список упорядковується по убуванню відміченої з допомогою одної з радіо-кнопок характеристики ( у разі вибору Price - за збільшенням). Пункт меню Best активізується. 5) По Best відкривається вікно повідомлень, що містить інформацію про комп'ютер що володіє якнайкращою характеристикою, вибраною в діалоговому вікні. Варіант 10.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу., варіант. 2) Створити меню вигляду: List Pentium 4 Athlon Show Quit По Quit застосування завершується. По About видається інформація про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Show відкривається діалогове вікно, що містить: - вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з двох кнопок Radio Button: Hard drive, Price; - OK, Cancel - кнопки типу Button. 5) По Pentium 4 або Athlon в діалогове вікно, що містить вікно-список і кнопку OK, виводиться список комп'ютерів відповідного типу, впорядкований по убуванню відміченої за допомогою однієї з радіо-кнопок характеристики. Варіант 11.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Information (підменю Show About Quit ) Choice Help

Page 84: метуказлабраб ооп 2011укр

84

Пункт Choice заборонений. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника.

3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Show відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - вікно-редактор для введення мінімальної місткості диска; - вікно-редактор для введення максимальної прийнятної ціни; - Arrange,OK, Cancel - кнопки типу Button.

По натисненню Arrange список упорядковується по убуванню характеристики Service. Пункт меню Choice активізується. 5) По Choice відкривається діалогове вікно, що містить список комп'ютерів, які задовольняють введеним обмеженням. Варіант 12.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Tops About Quit List Chart Пункт Chart заборонений. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією - статичне вікно над списком - заголовки граф - групу з трьох кнопок RADIOBUTTON: Overall, Performance, Service - OK, Cancel - кнопки типу BUTTON.

Пункт меню Chart активізується. 5) По Chart в головне вікно застосування виводиться графічна ілюстрація величини вибраної характеристики у вигляді горизонтальної стовпчикової діаграми. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 13.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про кращі комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: List About Quit По Quit застосування завершується. По About видається інформація про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з трьох кнопок RADIOBUTTON: Overall, Performance, Service; - однорядкове вікно-редактор для виведення інформації про комп'ютер, що володіє

найменшим відношенням ціни до вибраної характеристики; - групу з двох кнопок RADIOBUTTON: Pentium-4, Athlon; - Show the best,OK, Cancel - кнопки типу BS_PUSHBUTTON.

По натисненню Show the best у вікно-редактор виводиться інформація про комп'ютер що володіє якнайкращою характеристикою серед комп'ютерів вибраного типа.

Page 85: метуказлабраб ооп 2011укр

85

Варіант 14.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант 2) Створити меню вигляду: Characteristics Chart About Quit По Quit застосування завершується. По About видається інформація про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Characteristics відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - OK, Cancel - кнопки типу BS_PUSHBUTTON.

5) По Chart в головне вікно застосування виводиться графічна ілюстрація величини вартості комп'ютерів у вигляді горизонтальної стовпчикової діаграми. Комп'ютери з максимальною і мінімальною вартістю виділяються різними кольорами. Зображення повинне масштабуватися при зміні розмірів вікна Варіант 15.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Notebooks Your choice Help Show Quit Пункт Your choice заборонений. По Quit застосування завершується. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Show відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - вікно-редактор для введення мінімальної місткості диска; - вікно-редактор для введення максимальної прийнятної ціни; - групу з двох кнопок RADIOBUTTON: Hard drive, Price; - OK, Cancel - кнопки типу BUTTON.

Пункт меню Your choice активізується. 5) По Your choice відкривається діалогове вікно, що містить список комп'ютерів, що задовольняє введеним обмеженням і впорядкований по відміченій характеристиці.

Варіант 16.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: Show Diagram Clear About Quit По Quit застосування завершується. По About видається інформація про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Show відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - вікно-редактор для введення максимальної прийнятної ціни; - OK, Cancel - кнопки типу BUTTON.

Page 86: метуказлабраб ооп 2011укр

86

5) По Diagram в головне вікно застосування виводиться графічна ілюстрація величини вартості комп'ютерів, що задовольняють введеному обмеженню, у вигляді горизонтальної стовпчикової діаграми, впорядкованої за збільшенням вартості. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 17.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про комп'ютери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: List Chart About Quit Select Show Пункт Chart заборонений. По Quit застосування завершується. По About відкривається вікно з інформацією про розробника. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - OK - кнопку типу BUTTON.

Пункт меню Chart активізується. 5) По Select відкривається діалогове вікно, що містить групу з трьох кнопок RADIOBUTTON: Price, HDD, RAM, а також кнопку OK. 5) По Show в головне вікно застосування виводиться графічна ілюстрація величини вибраної характеристики у вигляді горизонтальної стовпчикової діаграми. Комп'ютери з максимальною і мінімальною характеристикою виділяються різними кольорами. Зображення повинне масштабуватися при зміні розмірів вікна. Варіант 18.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про лазерні принтери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: List of printers Choice Address Quit По Quit застосування завершується. По Address відкривається вікно з інформацією про фірму (адреса, телефони). 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List of printers відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з трьох кнопок RADIOBUTTON: ppm, dpi, price; - вікно-редактор для введення номера рядка, що містить вибраний принтер; - Arrange,OK, Cancel - кнопки типу BUTTON.

По натисненню Arrange список упорядковується по убуванню відміченої за допомогою одного з радіо-кнопок характеристики 5) По Choice відкривається вікно повідомлень, що містить інформацію про наявність вибраного комп'ютера на складі. Варіант 19.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про лазерні принтери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант.

Page 87: метуказлабраб ооп 2011укр

87

2) Створити меню вигляду: Printer Quit Full list Cheepest По Quit застосування завершується. 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По Full list відкривається діалогове вікно, що містить:

- вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з двох кнопок RADIOBUTTON: 300 dpi, 600 dpi; - вікно-редактор для введення мінімальної прийнятної швидкості роботи принтера; - OK, Cancel - кнопки типу BUTTON.

5) По Selected list видається список принтерів, що задовольняють введеним обмеженням і впорядкований за збільшенням вартості. 6) По Cheepest видається інформація про найбільш дешевий принтер і повідомлення про те, чи є він на складі. Варіант 20.

Написати застосування Windows, яке за заданими у файлі початковими даними виводить інформацію про лазерні принтери. Етапи виконання роботи. 1) Створити головне вікно. Заголовок містить ФІО, групу, варіант. 2) Створити меню вигляду: List of printers Diagram Address Quit По Quit застосування завершується. По Address відкривається вікно з інформацією про фірму (адреса, телефони). 3) При запуску застосування з файлу читаються початкові дані (файл сформувати самостійно). 4) По List of printers відкривається діалогове вікно, що містить: - вікно-список з введеною інформацією; - статичне вікно над списком - заголовки граф; - групу з чотирьох кнопок CHECKBOX: 4ppm, 8 ppm, 12 ppm, 16 ppm; - вікно-редактор для введення максимальної прийнятної ціни; - OK, Cancel - кнопки типу BUTTON. 5) По Diagram в головне вікно застосування виводиться графічна ілюстрація величини вартості принтерів, що задовольняють введеному обмеженню, у вигляді горизонтальної стовпчикової діаграми, впорядкованої за збільшенням вартості. Зображення повинне масштабуватися при зміні розмірів вікна.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати завдання згідно своєму варіанту.

Вправа 1. Приклад використання меню

1. Почніть із створення нового Windows Application. Назвіть його MenuExample.

2. Додайте у форму елементи MenuStrip і ContextMenuStrip, за допомогою подвійного клацання мишею на відповідних елементах, що знаходяться в панелі інструментів. Назвіть ці елементи відповідно menuStripFiles і contextMenuStripFonts.

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

Page 88: метуказлабраб ооп 2011укр

88

Назва Текст

toolStripMenuItemFiles &Files

newToolStripMenuItem &New

openToolStripMenuItem &Open

saveToolStripMenuItem &Save

toolStripMenuItem1 -

exitToolStripMenuItem E&xit

4. Виберіть контекстне меню і створіть наступні пункти меню точно так, як ви робили це вище.

Назва Текст

boldToolStripMenuItem &Bold

italicToolStripMenuItem &Italic

5. Додайте до форми один елемент RichTextBox. Назвіть його rtfText і надайте його властивості Dock значення Fill, для того, щоб воно заповнило всю форму цілком, і очистьте його властивість Text.

6. Виберіть елемент RichTextBox і виберіть властивість ContextMenuStrip. З розкриваного списку виберіть contextMenuStripFonts для того, щоб прив'язати контекстне меню до елементу RichTextBox.

Додавання обробників подій

7. Тепер слід додати код в наші меню. Ми не ускладнюватимемо методи, відповідні пунктам меню Open, Save і New, і для демонстраційних цілей використовуватимемо фіксований файл. Для того, щоб додати обробник події Click в який-небудь пункт меню, слід просто двічі клацнути на ньому мишею. Ми додамо обробники для наступних пунктів меню: New, Open, Save і Exit.

private void newToolStripMenuItem_Click(object sender, EventArgs e) { this.rtfText.Clear(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { try { this.rtfText.LoadFile("../../test.rtf"); } catch (System.Exception err) { MessageBox.Show("Error while loading:\n" + err.Message); } } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { try { this.rtfText.SaveFile("../../test.rtf"); } catch (System.Exception err) {

Page 89: метуказлабраб ооп 2011укр

89

MessageBox.Show("Error while saving:\n" + err.Message); } } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit();

}

8. На цьому робота з основним меню завершена, і тепер можна перейти до контекстного меню. Ми додаємо обробник подій Click точно так, як і робили це для основного меню – за допомогою подвійного клацання мишею на пунктах і внесення наступного коду:

private void boldToolStripMenuItem_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Bold ? rtfText.SelectionFont.Style & ~FontStyle.Bold : rtfText.SelectionFont.Style | FontStyle.Bold)); rtfText.SelectionFont = newFont; } private void italicToolStripMenuItem_Click(object sender, EventArgs e) { Font newFont = new Font(rtfText.SelectionFont, (rtfText.SelectionFont.Italic ? rtfText.SelectionFont.Style & ~FontStyle.Italic : rtfText.SelectionFont.Style | FontStyle.Italic)); rtfText.SelectionFont = newFont;

}

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

Після запуску застосування, набору і форматування тексту шляхом виклику контекстного меню по натисненню правої кнопки миші, може вийти щось схоже на таке:

Вправа 2. Побудова призначених для користувача діалогових вікон

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

Призначені для користувача діалогові вікна формуються самим користувачем для вирішення його специфічних задач. У просторі імен System.Windows.Forms не існує спеціального класу “Dialog”

Page 90: метуказлабраб ооп 2011укр

90

для діалогових вікон. Діалогове вікно – це просто стилізована форма (клас Form). Наприклад, багато діалогових вікон мають незмінні розміри, тому властивість форми FormBorderStyle необхідно встановити в FormBorderStyle.FixedDialog. Крім того, для діалогових вікон властивості MinimizeBox і MaximizeBox встановлюються в false. Таким чином, діалогове вікно конструюється фіксованим. І на закінчення, якщо ви виставите властивість ShowInTaskbar в false, то ваше вікно не зможе бути видимим в панелі задач Windows XP.

1. Щоб проілюструвати роботу з діалоговими вікнами, створіть нове Windows Application і назвіть його SimpleModalDialog.

2. За допомогою елементу управління MenuStrip створіть головне меню з пунктами File (підпункт Exit) і Tools (підпункт Configure).

3. Створіть обробники подій Click для пунктів меню Exit і Configure.

4. Крім того, визначте строкове поле з ім'ям userMessage в класі форми і відобразьте вміст цього поля в обробнику події Paint для форми. Усередині файлу Form1.cs одержимо наступний код:

public partial class Form1 : Form { private string userMessage = "Default Message"; public Form1() { InitializeComponent(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } private void configureToolStripMenuItem_Click(object sender, EventArgs e) { //We will implement this method in just а bit ... } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics;

g.DrawString(userMessage, new Font("Times New Roman", 24), Brushes.DarkBlue, 50, 50);

}

}

5. Додайте нову форму до поточного проекту, використовуючи меню Project / Add New Windows Form, і назвіть її UserMessageDialog.cs. Встановіть властивості ShowInTaskbar, MinimizeBox і MaximizeBox в false.

6. Сформуйте призначений для користувача інтерфейс діалогового вікна, помістивши в нього дві кнопки (Button), поле введення txtUserInput (TextBox) і напис (Label) (Мал. 3).

Мал. 3. Призначене для користувача діалогове вікно

Page 91: метуказлабраб ооп 2011укр

91

7. Створіть призначену для користувача властивість Message в класі діалогового вікна, пов'язану з текстом, користувачем, що вводиться.

public partial class UserMessageDialog : Form { public UserMessageDialog() { InitializeComponent(); } public string Message { set { txtUserInput.Text = value; } get { return txtUserInput.Text; } }

}

Властивість DialogResult

8. І, як рішення фінальної задачі по створенню призначеного для користувача інтерфейсу, виберіть кнопку OK в дизайнері форми і знайдіть для неї властивість DialogResult. Назначте DialogResult.OK кнопці OK і DialogResult.Cancel кнопці Cancel.

Що означає привласнення кнопці властивості DialogResult? Ця властивість може бути привласнена будь-якому типу кнопок (як і всій формі в цілому), і дозволяє батьківській формі визначити, яку кнопку в діалоговому вікні натиснув користувач.

9. Створіть наступний обробник пункту меню Configure:

private void configureToolStripMenuItem_Click(object sender, EventArgs e) { //Створення екземпляра UserMassageDialog UserMessageDialog dlg = new UserMessageDialog(); // Помістити поточне повідомлення в TextBox dlg.Message = userMessage; // Якщо користувач натиснув кнопку OK, відобразити повідомлення if (DialogResult.OK == dlg.ShowDialog()) { userMessage = dlg.Message; Invalidate(); } dlg.Dispose();

}

Тут ви показуєте діалог UserMessageDialog шляхом виклику методу ShowDialog. Цей метод показує діалогове вікно як модальний діалог, що означає, як ви пам'ятаєте, те, що користувач не може перемкнутися на вікно головної форми до тих пір, поки не закриє діалогове вікно, натиснувши одну з кнопок OK або Cancel.

10. Запустіть і протестуйте застосування.

Методичні вказівки і теоретичні відомості.

Застосування Windows Forms

Велика частина функціональних можливостей, необхідних для створення застосувань Windows Forms, знаходиться в просторі імен System.Windows.Forms. Створимо просте застосування Windows Forms, що виводить порожню форму на екран. Цей приклад не використовуватиме Visual Studio .NET. Його можна ввести в будь-якому текстовому редакторі і відкомпілювати за допомогою компілятора командного рядка. Ось текст даного застосування (файл MyForm.cs):

Page 92: метуказлабраб ооп 2011укр

92

using System; using System.Windows.Forms;

namespace NotepadForms { public class MyForm : System.Windows.Forms.Form { public MyForm() { this.Text = "Hello Form"; } [STAThread] static void Main() { Application.Run(new MyForm()); }

}

}

Відкомпілювати цей файл можна за допомогою однієї з команд:

csc MyForm.cs

csc MyForm.cs /reference:System.dll /reference:System.Windows.Forms.dll

Перемикач /reference задає бібліотеки, необхідні для функціонування програми. Власне кажучи, компілятор csc автоматично підключає всі головні системні бібліотеки DLL.

Не дивлячись на те, що наше застосування не дуже корисне, воно, проте, містить всього декілька рядків тексту і представляє повнофункціональне застосування Windows.

Давайте додамо нашому застосуванню більшої функціональності. Створимо застосування для

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

Мал. 4. Ця форма містить кнопку Load і елемент управління PictureBox.

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

Page 93: метуказлабраб ооп 2011укр

93

using System; using System.Windows.Forms;

[assembly: System.Reflection.AssemblyVersion("1.2")] namespace MyNamespace { public class MyForm : Form { private Button btnLoad; private PictureBox pbxPhoto;

public MyForm() { this.Text = "Hello Form 1.2"; // Create and configure а button btnLoad = new Button();

btnLoad.Text = "&Load"; btnLoad.Left = 10;

btnLoad.Top = 10;

// Create and configure а picture box pbxPhoto = new PictureBox();

pbxPhoto.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;

pbxPhoto.Width = this.Width / 2; pbxPhoto.Height = this.Height / 2; pbxPhoto.Left = (this.Width - pbxPhoto.Width) / 2;

pbxPhoto.Top = (this.Height - pbxPhoto.Height) / 2;

// Add our new controls to the form this.Controls.Add(btnLoad); this.Controls.Add(pbxPhoto);

} [STAThread] public static void Main() { Application.EnableVisualStyles(); Application.Run(new MyForm()); } } }

Наступна зміна в нашій маленькій програмі дозволить користувачу клацнути на кнопці Load і відобразити вибраний графічний файл в елементі управління PictureBox. Результат показаний на малюнку 5.

Рис 5. Зображення тут масштабується в межах PictureBox.

Виправіть вашу програму відповідно до наступного лістингу:

Page 94: метуказлабраб ооп 2011укр

94

using System; using System.Drawing;

using System.Windows.Forms;

[assembly: System.Reflection.AssemblyVersion("1.3")] namespace MyNamespace { public class MyForm :Form { Button btnLoad; PictureBox pbxPhoto; public MyForm() { this.Text = "Hello Form 1.3"; // Create and configure а button btnLoad = new Button(); btnLoad.Text = "&Load"; btnLoad.Left = 10; btnLoad.Top = 10; btnLoad.Click += new EventHandler(this.HandleLoadClick);

// Create and configure а picture box pbxPhoto = new PictureBox(); pbxPhoto.BorderStyle = BorderStyle.Fixed3D; pbxPhoto.Width = this.Width / 2; pbxPhoto.Height = this.Height / 2; pbxPhoto.Left = (this.Width - pbxPhoto.Width) / 2; pbxPhoto.Top = (this.Height - pbxPhoto.Height) / 2; pbxPhoto.SizeMode = PictureBoxSizeMode.Zoom;

// Add our new controls to the form this.Controls.Add(btnLoad); this.Controls.Add(pbxPhoto); } private void HandleLoadClick(object sender, System.EventArgs e) { OpenFileDialog dlg = new OpenFileDialog();

dlg.Title = "Open Photo"; dlg.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";

if (dlg.ShowDialog() == DialogResult.OK) { pbxPhoto.Image = new Bitmap(dlg.OpenFile());

} dlg.Dispose();

}

[STAThread] public static void Main() { Application.EnableVisualStyles(); Application.Run(new MyForm()); } } }

Новий командний рядок для компілятора буде таким:

csc MyForm.cs /r:System.dll /r:System.Windows.Forms.dll /r:System.Drawing.dll

І остання тема, пов'язана з нашим застосуванням, – це реакція на зміну розмірів форми. Для тих, хто знає Microsoft Foundation Classes (MFC) і Visual C++ 6.0, відомо, що це вимагає певної витрати праці. Рішення цієї задачі в .NET значно полегшено.

Перед тим, як подивитися нову версію коду, змініть розміри вікна існуючої програми і подивіться, що відбудеться. Ви відмітите, що позиція кожного елементу управління буде фіксована щодо лівого верхнього кута форми. Ми б вважали за краще, щоб елемент управління PictureBox

Page 95: метуказлабраб ооп 2011укр

95

змінював свої розміри відповідно до зміни розміру вікна, як показано на малюнку 6. На щастя, базовий клас Control має в своєму розпорядженні певні властивості, що реагують на зміну розмірів вікна.

Рис.6. Елемент управління змінює розміри.

Відкоректуйте свій код у відповідність з лістингом:

using System; using System.Drawing; using System.Windows.Forms; [assembly: System.Reflection.AssemblyVersion("1.4")] namespace MyNamespace { public class MyForm :Form { Button btnLoad; PictureBox pbxPhoto; public MyForm() { this.Text = "Hello Form 1.4"; // Create and configure а button btnLoad = new Button(); btnLoad.Text = "&Load"; btnLoad.Left = 10; btnLoad.Top = 10; btnLoad.Click += new EventHandler(this.HandleLoadClick); btnLoad.Anchor = AnchorStyles.Top | AnchorStyles.Left;

// Create and configure а picture box pbxPhoto = new PictureBox(); pbxPhoto.BorderStyle = BorderStyle.Fixed3D; pbxPhoto.Width = this.Width / 2; pbxPhoto.Height = this.Height / 2; pbxPhoto.Left = (this.Width - pbxPhoto.Width) / 2; pbxPhoto.Top = (this.Height - pbxPhoto.Height) / 2; pbxPhoto.SizeMode = PictureBoxSizeMode.Zoom; pbxPhoto.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

// Add our new controls to the form this.Controls.Add(btnLoad); this.Controls.Add(pbxPhoto); } private void HandleLoadClick(object sender, System.EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Open Photo"; dlg.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*"; if (dlg.ShowDialog() == DialogResult.OK) {

Page 96: метуказлабраб ооп 2011укр

96

pbxPhoto.Image = new Bitmap(dlg.OpenFile()); } dlg.Dispose(); } [System.STAThread] public static void Main() { Application.EnableVisualStyles(); Application.Run(new MyForm()); } } }

Стандартні елементи управління і компоненти

Кнопки

Клас Button представляє командну кнопку і є похідним від класу ButtonBase. Найбільш поширеним є написання коду обробника події Click для кнопки. За допомогою методу PerformClick ви можете імітувати натиснення на кнопку без її реального натиснення користувачем. Метод NotifyDefault, що приймає параметр логічного типа, повідомляє кнопку, що її слід зображати як кнопку за умовчанням (default button). Кнопка за умовчанням зображається на формі із злегка потовщеною межею. Щоб визначити кнопку як кнопку за умовчанням, ви повинні встановити властивість AcceptButton форми на кнопку. Тоді у разі натиснення користувачем клавіші Enter згенерує подія Click для кнопки за умовчанням.

На кнопці можна поміщати текст або зображення. Зображення поставляються за допомогою об'єкту ImageList або властивості Image. Як Text так і Image мають властивість Align для вирівнювання тексту або зображення на кнопці.

CheckBox

Елемент управління CheckBox також є похідним від класу ButtonBase, і використовується для підтримки двох або трьох станів. Якщо ви встановите властивість ThreeState в true, то властивість CheckState для CheckBox може приймати одне з трьох значень:

Checked – прапорець CheckBox відмічений;

Unchecked – прапорець CheckBox не відмічений;

Indeterminate – в цьому стані елемент CheckBox зображається сірим кольором і є недоступним.

Значення Indeterminate можна встановити тільки програмним шляхом. Це зручно, якщо ви хочете повідомити користувача, що якась опція йому недоступна. Ви також можете контролювати властивість Checked, якщо вам потрібен булевий тип.

Якщо властивості CheckState або Checked змінюються, то відбуваються події CheckedChanged або CheckStateChanged. Перехоплення цих подій корисне, коли необхідно встановити значення інших величин, залежних від стану елементу CheckBox. Наприклад, подію CheckedChanged для декількох елементів CheckBox можна обробити так:

private void checkBoxChanged(object sender, EventArgs e) { CheckBox checkBox = (CheckBox)sender; MessageBox.Show(checkBox.Name + " new value is " + checkBox.Checked.ToString()); }

Page 97: метуказлабраб ооп 2011укр

97

RadioButton

Елемент управління RadioButton також є похідним від класу ButtonBase, і звичайно використовується в групі. Іноді потрібно забезпечити вибір тільки однієї з декількох опцій.

Властивість Appearance може приймати значення перераховного типа: Button або Normal. При виборі Normal радіокнопка виглядає як маленьке коло з міткою поряд. Вибір кнопки закрашує коло, а вибір іншої кнопки прибирає зафарбовування. При виборі значення Button радіокнопка виглядає як звичайна кнопка, але вона працює як прапор – у вибраному або не вибраному стані.

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

Подія CheckedChanged генерується, коли значення властивості Checked змінюється.

ComboBox, ListBox, і CheckedListBox

Класи ComboBox, ListBox, і CheckedListBox є похідними від класу ListControl. Цей клас забезпечує базову функціональність списку. Найбільш важливим для списків є додавання і вибір даних. Який із списків вибрати як правило визначається тим, яким чином цей список використовується, і типом даних, що представляються в списку. Якщо потрібно забезпечити вибір декількох елементів списку або користувачу треба бачити декілька елементів списку одночасно, то підійде ListBox або CheckedListBox. Якщо потрібно вибрати тільки один елемент списку за один раз, то можливо кращим вибором буде ComboBox.

Перед використанням в список треба додати дані. Це робиться шляхом додавання об'єктів в ListBox.ObjectCollection. Цю колекцію представляє властивість Items. Через те, що в колекції зберігаються об'єкти, будь-який правильний тип .NET може бути збережений в списку. Щоб ідентифікувати елементи списку, використовуються дві важливі властивості. Першою є властивість DisplayMember. Ця властивість повідомляє список, яка властивість вашого об'єкту повинна бути відбита в списку. Другою є властивість ValueMember, задаюча властивість об'єкту, яку ви хочете повертати. Якщо в список додані рядки, то значенням за умовчанням для цих властивостей є строковий тип.

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

private void LoadList(Control ctrlToLoad) { ListBox tmpCtrl = null; if (ctrlToLoad is ListBox) tmpCtrl = (ListBox)ctrlToLoad; tmpCtrl.Items.Clear(); tmpCtrl.DataSource = null; if (radioButton1.Checked) { //load objects tmpCtrl.Items.Add(new Vendor("XYZ Company", "555-555-1234")); tmpCtrl.Items.Add(new Vendor("ABC Company", "555-555-2345")); tmpCtrl.Items.Add(new Vendor("Other Company", "555-555-3456")); tmpCtrl.DisplayMember = "Name"; } else { tmpCtrl.Items.Clear(); tmpCtrl.Items.Add("XYZ Company"); tmpCtrl.Items.Add("ABC Company"); tmpCtrl.Items.Add("Other Company"); } }

Page 98: метуказлабраб ооп 2011укр

98

Після завантаження даних для виділення елементів списку можна використовувати властивості SelectedItem і SelectedIndex. Властивість SelectedItem повертає тільки що вибраний об'єкт. Якщо список налаштований на множинний вибір, то вибрані об'єкти містить колекція SelectObject.

Якщо потрібен елемент по певному індексу, то можна використовувати властивість Items для доступу до ListBox.ObjectCollection.

Якщо для заповнення списку використовувався DataBinding, то властивість SelectedValue повертатиме властивість-значення вибраного об'єкту, яка була встановлена властивістю ValueMember. Наприклад, якщо у властивість ValueMember встановлений Телефон (Phone), то SelectedValue повертатиме номер телефону вибраного об'єкту. Щоб використовувати ValueMember і SelectValue список повинен бути заповнений через властивість DataSource. Перш ніж призначати властивість DataSource, необхідно завантажити об'єкти в ArrayList або в будь-яку IList-колекцію. Це демонструє наступний короткий приклад:

listBox1.DataSource = null; System.Collections.ArrayList lst = new System.Collections.ArrayList(); lst.Add(new Vendor("XYZ Company", "555-555-1234")); lst.Add(new Vendor("ABC Company", "555-555-2345")); lst.Add(new Vendor("Other Company", "555-555-3456")); lst.Add(new Vendor("Another Company", "555-555-4567")); lst.Add(new Vendor("More Company", "555-555-6789")); lst.Add(new Vendor("Last Company", "555-555-7890")); listBox1.Items.Clear(); listBox1.DataSource = lst; listBox1.DisplayMember = "Name"; listBox1.ValueMember = "Phone";

Використання SelectedValue без використання DataBinding генеруватиме виключення NullException.

Наступні рядки коду демонструють доступ до елементів списку:

//obj is set to the selected Vendor object obj = listBox1.SelectedItem; //obj is set to the Vendor object with index of 3 (4th object) obj = listBox.Items[3]; //obj is set to the values of the Phone property of the selected vendor object //This example assumes that databinding was used to populate the list listBox1.ValuesMember = "Phone"; obj = listBox1.SelectValue;

Властивість Items списку ComboBox повертає ComboBox.ObjectCollection. ComboBox є комбінація поля введення і списку. Ви встановлюєте стиль ComboBox передачею значення перераховного типа DropDownStyle властивості DropDownStyle. Наступна таблиця показує значення властивості DropDownStyle.

Таблиця 20. Значення властивості DropDownStyle.

Значення Опис

DropDown Текст в ComboBox редагований, і користувачі можуть вводити значення. Вони також повинні клацнути по стрілці, щоб розкрити список.

DropDownList Текст в ComboBox не редагований, і користувачі можуть просто вибирати значення.

Simple Те ж, що DropDown, але весь список завжди є видимим.

Page 99: метуказлабраб ооп 2011укр

99

DateTimePicker

DateTimePicker дозволяє користувачам вибирати дату та/або час в одному з форматів. Властивість Format може приймати значення Long, Short, Time, або Custom перераховного типа DateTimePickerFormat.

Є також властивості Text і Value. Властивість Text повертає текстове представлення дати-часу, тоді як властивість Value повертає об'єкт типу DateTime. Ви також можете встановити мінімально допустиму і максимально допустиму дату за допомогою властивостей MinDate і MaxDate.

При клацанні по стрілці з'являється календар, що дозволяє вибрати дату в календарі. Є властивості, що дозволяють вибрати зовнішній вигляд календаря.

ErrorProvider

ErrorProvider насправді є не елемент управління, а компонент. Коли ви перетягнете компонент на форму, він відображатиметься в полі компонентів під формою. Компонент ErrorProvider проявляє себе появою яскравої ікони поряд з елементом управління, коли поставлені умови порушаться. Припустимо, що ми маємо поле TextBox для введення віку. Ваші правила бізнесу говорять, що вік не може перевищувати 65. Якщо користувач спробує ввести вік, більший, ніж 65, ви повинні його інформувати про те, як правильно ввести це значення. Перевірка на введення правильної величини проводиться в події Validated поля введення TextBox. Коли перевірка виявила помилку, ви викликаєте метод SetError елементу управління, що викликав помилку, і виводите рядок з інформацією. Одночасно поряд з елементом управління почне пульсуюче світитися іконка, що інформує про помилку. При наведенні мишки на цю іконку з'явиться рядок з інформацією про помилку. На Мал.7 показано появу іконки при неправильному введенні.

Мал.7. Індикація неправильного введення.

Ви можете створити ErrorProvider для кожного елементу управління, здатного бути джерелом помилкового введення, проте при великій їх кількості це може стати громіздким. Кращим варіантом є використання одного елементу ErrorProvider і по події Validated викликати метод IconLocation, передаючи йому елемент управління, що викликав помилку. Далі ви викликаєте метод SetError. Якщо при перевірці умов помилки не виявлені, ви можете очистити ErrorProvider викликом SetError з порожнім рядком помилки. Наступний приклад показує, як це працює.

private void txtAge_Validating(object sender System.ComponentModel.CancelEventArgs e) { if(txtAge.TextLength > 0 && Convert.ToInt32(txtAge.Text) > 65) { errMain.SetIconAlignment((Control)sender ErrorIconAlignment.MiddleRight); errMain.SetError((Control)sender, "Value must be less then 65."); e.Cancel = true; } else { errMain.SetError((Control)sender, ""); } } private void txtZipCode_Validating(object sender System.ComponentModel.CancelEventArgs e) { if(txtZipCode.TextLength > 0 && txtZipCode.Text.Length != 5) { errMain.SetIconAlignment((Control)sender

Page 100: метуказлабраб ооп 2011укр

100

ErrorIconAlignment.MiddleRight); errMain.SetError((Control)sender, "Must be 5 charactors.."); e.Cancel = true; } else { errMain.SetError((Control)sender, ""); } }

Якщо перевірка виявить помилку (наприклад, в поле txtAge введено значення, більше 65), то буде викликаний метод SetIcon ErrorProvider-ра errMain.

HelpProvider

HelpProvider, як і ErrorProvider, є компонентом, а не елементом управління. HelpProvider дає можливість пов'язати з елементами управління рядка допомоги. Для цього викликається метод SetShowHelp елементу управління, значення булевого типа визначає, чи показуватиметься допомога. Властивість HelpNamespace дозволяє встановити файл допомоги. Якщо властивість HelpNamespace встановлена, файл допомоги буде доступний при натисненні F1, якщо елемент управління, який ви зареєстрували в HelpProvider, буде у фокусі. Ви можете встановити ключове слово для файлу допомоги через метод SetHelpKeyword.

Властивість SetHelpNavigator через перелік типу HelpNavigator встановлює, який елемент файлу допомоги відображатиметься. Ви можете встановити його на специфічну тему, на індекс, на зміст або на сторінку пошуку. Властивість SetHelpString пов'язує рядок з допомогою з елементом управління. Якщо властивість HelpNamespace не встановлена, то при натисненні F1 цей текст буде показаний в спливаючому вікні. Додамо HelpProvider до попереднього прикладу.

helpProvider1.SetHelpString(txtAge,"Enter an age that is less than 65"); helpProvider1.SetHelpString(txtZipCode,"Enter а 5 digit zip code");

ImageList

Компонент ImageList, у відповідність з своєю назвою, представляє список зображень. Звичайно цей компонент використовується для зберігання колекції зображень, які використовуються на панелі інструментів або в деревовидному списку TreeView. Багато елементів управління мають властивість ImageList. Звичайно ця властивість поєднується з властивістю ImageIndex. Для додавання зображень в ImageList треба скористатися методом Add властивості ImageList.Images. Властивість Images повертає ImageCollection.

Двома найбільш використовуваними властивостями є ImageSize і ColorDepth. ImageSize використовує структуру Size. Величиною за умовчанням є 16, але можна вибрати будь-яке число в діапазоні від 1 до 255. Значення ColorDepth можна вибирати від 4 bit до 32 bit.

ListView

Графічний список ListView дає можливість представляти елементи одним з чотирьох способів. Ви можете відображати текст разом з великими іконками, текст разом з малими іконками, або текст з малими іконками у вертикальному списку, або у вигляді за умовчанням, який припускає відображення текстової складової плюс будь-яка з sub items в стовпцях.

ListView містить колекцію ListViewItems. ListViewItems дозволяють встановлювати властивість Text, що відображається в ListView. ListViewItems має властивість SubItems, що містить текст, що відображається при детальному розгляді.

Page 101: метуказлабраб ооп 2011укр

101

Наступний приклад показує, як ви можете використовувати ListView. Цей приклад містить короткий список країн. Кожен об'єкт типу CountryList має поля для імені країни, абревіатури країни і грошової одиниці. Ось код для класу CountryList

using System; namespace FormsSample {

public class CountryItem : System.Windows.Forms.ListViewItem {

string _cntryName = ""; string _cntryAbbrev = "";

public CountryItem(string countryName string countryAbbreviation, string currency) { _cntryName = countryName; _cntryAbbrev = countryAbbreviation; base.Text = _cntryName; base.SubItems.Add(currency); }

public string CountryName { get {return _cntryName;} }

public string CountryAbbreviation { get {return _cntryAbbrev;} }

} }

Відмітимо, що клас CountryItem є спадкоємцем від класу ListViewItem. Це зроблено тому, що в ListView можна поміщати тільки об'єкти, похідні від ListViewItem. У конструкторі ви передаєте ім'я країни в полі базового класу base.Text, а грошову одиницю додаєте до властивості base.SubItems. Це приведе до відображення імені країни в списку, а грошової одиниці в окремому стовпці при детальному розгляді.

Далі необхідно додати декілька елементів CountryItem в ListView.

lvCountries.Items.Add(new CountryItem("United States","US","Dollar")); lvCountries.Items[0].ImageIndex = 0; lvCountries.Items.Add(new CountryItem("Great Britain", "GB", "Pound")); lvCountries.Items[1].ImageIndex = 1; lvCountries.Items.Add(new CountryItem("Canada", "CA", "Dollar")); lvCountries.Items[2].ImageIndex = 2; lvCountries.Items.Add(new CountryItem("Japan", "JP", "Yen")); lvCountries.Items[3].ImageIndex = 3; lvCountries.Items.Add(new CountryItem("Germany", "GM", "Deutch Mark")); lvCountries.Items[4].ImageIndex = 4;

Тут ми додаємо нові CountryItem до колекції Items елементу управління ListView (lvCountries). Звертаємо увагу, що ми встановлюємо властивість ImageIndex елементу списку після його додавання. Є два об'єкти ImageIndex, один для великих іконок, інший для малих іконок (властивості SmallImageList і LargeImageList). У даному прикладі список зображень містить іконки прапорів країн.

На вершині форми можна помістити комбінований список ComboBox (cbView), який відображатиме значення переліку View. Ви можете додати елементи в cbView так:

Page 102: метуказлабраб ооп 2011укр

102

cbView.Items.Add(View.LargeIcon); cbView.Items.Add(View.SmallIcon); cbView.Items.Add(View.List); cbView.Items.Add(View.Details); cbView.SelectedIndex = 0;

У обробник події SelectedIndexChanged елементу cbView додамо єдиний рядок коду:

lvCountries.View = (View)cbView.SelectedItem;

Цей код встановлює властивість View графічного списку lvCountries в нове значення, вибране в списку ComboBox.

І останнє. Ви повинні додати стовпці в колекцію Columns. Стовпці потрібні для детального вигляду. У нашому випадку треба додати два стовпці: ім'я країни і грошову одиницю. Порядок колонок буде наступний: спочатку стовпець для поля Text елементу списку ListViewItem, далі стовпець для кожного елементу колекції ListViewItem.SubItem у порядку їх появи в колекції. Ви можете додати стовпці одним з двох способів. У першому способі ви створюєте об'єкт ColumnHeader і встановлюєте його властивість Text і можливо властивості Width і Alignment. Після створення об'єкту ColumnHeader ви можете його додати у властивість Columns. Інший спосіб додавання стовпців полягає у використанні перевантаженого методу Columns.Add. Це дозволить додавати Text, Width і Alignment.

lvCountries.Columns.Add("Country",100, HorizontalAlignment.Left); lvCountries.Columns.Add("Currency",100, HorizontalAlignment.Left);

Якщо ви встановите властивість AllowColumnReorder в true, користувач зможе перетягувати заголовки стовпців, міняючи їх порядок.

Властивість CheckBoxes списку ListView показує чекбоксы після елементів в ListView. Це дозволить користувачу легко проводити множинний вибір в ListView.

PictureBox

Елемент управління PictureBox використовується для відображення зображень. Зображення може бути у форматі BMP, JPEG, GIF, PNG, метафайлом або піктограмою (icon). Властивість SizeMode використовує перелік PictureBoxSizeMode для завдання того, як зображення масштабуватиметься і позиціонуватиметься в елементі управління. Властивість SizeMode може приймати значення AutoSize, CenterImage, Normal, і StretchImage. Ви можете змінити розмір екрану PictureBox установкою властивості ClientSize.

У елемент управління PictureBox завантажується заздалегідь створений Image-based об'єкт. Наприклад, завантаження файлу формату JPEG в PictureBox виглядатиме так:

Bitmap myJpeg = new Bitmap("mypic.jpg"); pictureBox1.Image = (Image)myJpeg;

ProgressBar

Елемент ProgressBar візуалізує хід тривалих операцій. Для роботи ProgressBar необхідно задати властивості Minimum і Maximum. Ви встановлюєте властивість Step для завдання кроку приросту при кожному виклику методу PerformStep. Ви також можете використовувати метод Increment для нарощування величини при кожному виклику. Властивість Value повертає поточне значення ProgressBar. Ви можете використовувати властивість Text для інформування користувача про

Page 103: метуказлабраб ооп 2011укр

103

відсоток виконання операції. Є також властивість BackgroundImage для додання елементу управління особливого вигляду.

TextBox, RichTextBox і MaskedTextBox

Елемент TextBox є одним з найбільш використовуваних елементів панелі Toolbox. Класи TextBox, RichTextBox і MaskedTextBox є похідними від класу TextBoxBase. Цей клас надає властивості MultiLine і Lines. Кожен рядок тексту входить в масив рядків Lines. Властивість Text представляє весь текст як один рядок. TextLength – це повний розмір тексту. Властивість MaxLength є обмежувачем довжини тексту.

Властивості SelectedText, SelectionLength, і SelectionStart відносяться до виділеної ділянки тексту.

У елемент TextBox додані деякі цікаві властивості. Властивість AcceptsReturn булевого типа дає можливість приймати натиснення на клавішу Enter як перехід на новий рядок або натиснення кнопки за умовчанням. Властивість CharacterCasing визначає режим представлення тексту в TextBox, і може приймати одне з трьох значень: Lower, Normal або Upper. При виборі Lower текст представляється в нижньому регістрі, при виборі Upper – у верхньому регістрі незалежно від того, як текст реально вводиться. При виборі Normal текст відображається в тому вигляді, в якому він реально вводиться. Властивість PasswordChar представляє символ, який відображається в полі введення при наборі користувачем тексту. Воно звичайно використовується при введенні пароля або PIN-коду. Властивість text повертає реально введений текст.

Елемент управління RichTextBox надає можливості по форматуванню тексту, для цього він використовує формат Rich Text Format (RTF). Ви можете вибрати зміни форматів, через властивість Selection: SelectionFont, SelectionColor, і SelectionBullet, і форматування параграфа через SelectionIndent, SelectionRightIndent, і SelectionHangingIndent.

Текст, що міститься в елементі управління доступний через властивості Text або Rtf, причому Rtf представляє форматований текст.

Метод LoadFile може завантажити текст з файлу двома різними способами. Він може використовувати рядок, що містить шлях і ім'я файлу, або може використовувати потоковий об'єкт. Ви можете також встановити RichTextBoxStreamType. Таблиця 9 показує список можливих значень RichTextBoxStreamType.

Таблиця 9. Можливі значення властивості RichTextBoxStreamType.

Значення Опис

PlainText Не форматована інформація. У місцях, що містять OLE-об'єкти, поміщаються пропуски.

RichNoOleObjs Форматований текст, але в місцях, що містять OLE-об'єкти, поміщаються пропуски.

RichText Форматований RTF з OLE-об'єктами

TextTextOleObjs Простий текст з текстом, що заміщає OLE-об'єкти.

UnicodePlainText Те ж, що і PlainText, але в кодуванні Unicode

Метод SaveFile працює з тими ж параметрами, зберігаючи дані з елементу управління в спеціальному файлі.

Елемент управління MaskedTextBox дає можливість ввести обмеження на інформацію, що вводиться. Він також дає можливість автоматично форматувати введену інформацію. Для маскування і форматування призначеного для користувача введення використовуються декілька властивостей. Властивість Mask містить рядок маски. Рядок маски схожий на рядок, формату. Кількість допустимих символів, допустимі типи символів, формат даних, - все це вводиться через рядок Mask. Для перевірки і форматування даних можна також використовувати клас, похідний від MaskedTextProvider.

Page 104: метуказлабраб ооп 2011укр

104

Три різні властивості можуть повернути текст з MaskedTextBox. Властивість Text повертає текст у нинішній момент. Він може бути різним залежно від того, чи має елемент управління фокус і від властивості HidePromptOnLeave. Запрошенням є рядок, що підказує користувачу, який текст треба вводити. Властивість InputText завжди повертає тільки текст, який ввів користувач. Властивість OutputText повертає текст, що відформатував у відповідність з властивостями IncludeLiterals і IncludePrompt. Якщо, наприклад, маска створена для введення номера телефону, то рядок Mask можливо містить інтервали і тире. Вони будуть включені у властивість OutputText, якщо властивість IncludeLiteral має значення true.

Для MaskedTextBox визначені декілька додаткових подій. Події OutputTextChanged і InputTextChanged генеруються, коли InputText або OutputText змінюються.

Panel

Панель є елементом управління, що містить інші елементи управління. Для полегшення управління елементами вони групуються разом на панелі Panel. Наприклад, ви можете зробити неактивними всі елементи управління на панелі, зробивши саму панель не активною. Внаслідок того, що елемент Panel є спадкоємцем ScrollableControl, ви також можете скористатися перевагами властивості AutoScroll. Якщо ви маєте дуже багато елементи, щоб показати їх всіх на виділеній області, помістіть їх на панель і встановіть властивість AutoScroll в true.

Панель не показує за умовчанням меж, але установкою властивості BorderStyle в будь-яке значення, окрім none, ви можете використовувати Panel для візуального угрупування взаємно зв'язаних елементів. Це робить призначений для користувача інтерфейс більш дружнім.

Клас Panel є базовим для класів FlowLayoutPanel, TableLayoutPanel, TabPage, і SplitterPanel. За допомогою цих елементів управління можна створити багато складних, професійно виглядаючих форм і вікон. Панелі FlowLayoutPanel і TableLayoutPanel особливо корисні для створення форм, що змінюють розміри.

FlowLayoutPanel і TableLayoutPanel

Це нові елементи управління в .NET Framework. Як підказують їх імена, панелі пропонують можливість розміщення елементів згідно тій же парадигмі, що використовується в Web Form. Панель FlowLayoutPanel є контейнером, що дозволяє розташовувати елементи в горизонтальному або вертикальному напрямі. Напрям розташування елементів вибирається через властивість FlowDirection. Властивість WrapContents визначає, чи будуть елементи переміщатися на наступний рядок у разі зміни розмірів форми або у разі згортання елементів.

Панель TableLayoutPanel використовує табличне розташування елементів. Будь-який елемент Windows Forms може бути спадкоємцем TableLayoutPanel, у тому числі і сама TableLayoutPanel. Це посволяет добитися дуже гнучкого і динамічного дизайну. Коли елемент доданий на TableLayoutPanel, чотири додаткові властивості додаються в категорію Layout сторінки властивостей. Це Column, ColumnSpan, Row, і RowSpan. Подібно до html-таблиці на Web-сторінці, інтервали (spans) для стовпців і рядків можуть бути задані для кожного елементу управління. За умовчанням елемент управління центрується щодо елементу таблиці, але це можна змінити за допомогою властивостей Anchor і Dock.

Властивості за умовчанням для рядків і стовпців можуть бути змінені за допомогою властивостей RowStyles і ColumnsStyles. Ці колекції містять об'єкти RowStyle і ColumnsStyle відповідно. Ці об'єкти стилю мають загальну властивість SizeType. Властивість SizeType використовує SizeType-перелік для визначення того, як вимірюються ширина стовпця і висота рядка. Значеннями можуть бути AutoSize, Absolute, або Percent. Значення AutoSize розподіляє простір з урахуванням інших елементів. Значення Absolute дозволяє задати розмір в пікселях, значення Percent задає розмір у відсотках щодо батьківського елементу.

Page 105: метуказлабраб ооп 2011укр

105

Рядки, стовпці і дочірні елементи можуть бути додані або видалені в період виконання. Властивість GrowStyle використовує значення переліку TableLayoutPanelGrowStyle для того, щоб дозволити таблиці розширюватися при додаванні нових елементів в заповнену таблицю, або примусити таблицю зафіксувати свої розміри. Якщо вибрана величина FixedSized, то при спробі додати новий елемент генерується виключення AurgumentException. Якщо осередок в таблиці порожній, то елемент управління поміщається в порожній осередок. Ця властивість спрацьовує тільки тоді, коли таблиця заповнена, і додається новий елемент.

SplitContainer

Елемент управління SplitContainer реально представляє три елементи в одному. Він складається з двох панелей і роздільника. Користувач має можливість переміщати роздільник, змінюючи розміри панелей. Також можна змінювати розміри елементів на панелях. Кращим прикладом елементу SplitContainer є Провідник Windows. Ліва панель містить TreeView для представлення деревовидної структури директорій, а права панель містить ListView для представлення вмісту директорій.

SplitContainer може містити будь-які елементи управління, включаючи панелі вирівнювання і ще один SplitContainer.

Рух і позицію роздільника можна контролювати за допомогою властивостей SplitterDistance і SplitterIncrement. Властивість SplitterDistance визначає положення роздільника щодо лівої або верхньої межі елементу. Властивість SplitterIncrement визначає, на скільки пікселів переміщатиметься роздільник при перетяганні. Для панелей можна задати їх мінімальний розмір шляхом завдання властивостей Panel1MinSize і Panel2MinSize.

Роздільник може генерувати дві події, пов'язані з рухом: подія SplitterMoving і подія SplitterMoved. Перша подія відбувається при русі роздільника, а друге – після завершення перетягання. Вони обидва одержують як аргумент SplitterEventArgs, що містить X і Y координати лівої верхньої межі роздільника (SplitX і SplitY) і X і Y координати миші.

TabControl і TabPages

Елемент управління TabControl дозволяє групувати зв'язані по сенсу елементи в серію сторінок із закладками. TabControl управляє колекцією TabPages. Зовнішній вигляд TabControl контролюється декількома властивостями. Властивість Appearance використовує перелік TabAppearance для завдання зовнішнього вигляду закладок. Можливими значеннями є FlatButtons, Buttons, або Normal. Логічна властивість Multiline визначає, чи можна використовувати більше, ніж один рядок закладок. Якщо властивість Multiline встановлена в false, а всі закладки не можуть бути відображені, то з'явиться серія стрілок, що дозволяють проводити прокрутку.

Властивість Text елементу TabPage визначає напис на закладці.

Ви можете визначити поточну закладку, відстежуючи властивість SelectedTab. Подія SelectedIndex відбувається кожного разу при виборі нової закладки.

Меню, панель інструментів і рядок стану

Меню складає важливу складову частину будь-якого застосування. Для полегшення роботи із створення меню для застосувань в Visual Studio 2005 передбачений ряд нових керівників елементів, які дозволяють дуже швидко створювати прості меню, витрачаючи не набагато більше зусиль на створення складних.

Елемент управління ToolStrip

Новий клас ToolStrip (System.Windows.Forms.ToolStrip) розташований в секції Menus & Toolbars панелі інструментів Toolbox, замінює застарілий клас ToolBar і підтримує декілька елементів управління, включаючи ToolStripButton, ToolStripSplitButton, ToolStripDropDownButton Button,ToolStripLabel, ToolStripProgressBar, ToolStripSeparator, ToolStripCombobox, та ToolStripTextBox. Елемент ToolStrip представляється в сучасному Office-стилі, і підтримує теми

Page 106: метуказлабраб ооп 2011укр

106

Windows XP. Ви можете позиціонувати елемент ToolStrip шляхом вибору його властивості Dock і клацання по позиційному індикатору:

Мал. 8. Позиціонування елементу ToolStrip

Ви можете додавати елементи в ToolStrip різними способами. Клацання по кнопці "AddToolStrip", розташованій усередині ToolStrip, додає кнопку, а клацання по стрілці випадного списку дає можливість вибрати потрібний елемент управління.

Мал 9. Додавання елементів в ToolStrip.

Інший метод додавання елементів в ToolStrip полягає у виділенні smart tag для ToolStrip (стрілка в правому верхньому кутку елементу) і вибору пункту Edit Items. Редактор Items Collection Editor (див. Мал 10) дозволяє додавати нові елементи в ToolStrip и/или редагувати властивості існуючих елементів.

Мал.10 Редактор Items Collection Editor дозволяє управляти елементами в ToolStrip

Page 107: метуказлабраб ооп 2011укр

107

Вибір пункту "Insert Standard Items." у smart tag-меню автоматично додає стандартні кнопки для управління документом (New, Open, Save, Print, Cut, Copy, Paste, і Help).

Всі елементи ToolStrip items являються похідними від класу ToolStripItem, і підтримують такі властивості як Text, Image, ImageAlign, Enabled, і Visible.

Кожна кнопка в ToolStrip підтримує свою власну подію Click.

Ви не знайдете традиційного елементу управління ToolBar в панелі інструментів ToolBox. Він, як і інші елементи управління на зразок StatusBar (заміненого елементом управління StatusStrip), виключені з панелі ToolBox; проте, якщо ви хочете додати який-небудь традиційний елемент управління, ви можете натиснути праву кнопку миші на панелі ToolBox, вибрати Choose Items і вибрати елементи, які ви хочете додати, із списку, що з'явився.

Елемент управління StatusStrip

Новий клас StatusStrip (System.Windows.Forms.StatusStrip) розташований в секції Menus & Toolbars панелі інструментів Toolbox, є похідним від класу ToolStrip і замінює застарілий традиційний клас StatusBar. Він підтримує ряд ToolStrip items, таких як ToolStripStatusLabel, ToolStripProgressBar, ToolStripDropDownButton і ToolStripSplitButton. Подібно до елементу управління ToolStrip, він представляється в сучасному Office-стилі, і підтримує теми Windows XP.

Мал 11. Елемент StatusStrip підтримує різні режими відображення.

Будучи спадкоємцем від ToolStrip, елемент StatusStrip володіє приблизно такими ж можливостями, як і ToolStrip, наприклад, кожний елемент, що входить в StatusStrip, може мати свій обробник події Click.

Елемент управління MenuStrip

Новий клас MenuStrip (System.Windows.Forms.MenuStrip) розташований в секції Menus & Toolbars панелі інструментів Toolbox, теж є похідним від класу ToolStrip і замінює застарілий традиційний клас MainMenu. Він підтримує ряд елементів ToolStrip items, таких як ToolStripMenuItem, ToolStripComboBox, і ToolStripTextBox. Кожен об'єкт ToolStripMenuItem підтримує ряд властивостей, таких як Image, ToolTipText, і Font.

Ви можете додавати елементи меню одним з трьох варіантів. По-перше, як і для традиційного елементу MainMenu, ви можете створювати і редагувати меню вручну шляхом набору елементів прямо в меню. Другий підхід полягає у виборі пункту "Edit Items." у smart tag-меню і подальшою роботою в редакторі Items Collection Editor (Мал. 12).

Page 108: метуказлабраб ооп 2011укр

108

Мал.12. Управління елементом MenuStrip: редактор Items Collection Editor редагує елементи в MenuStrip

Третій і найбільш ефективний підхід полягає у виборі пункту "Insert Standard Items" з smart tag-

меню і автоматичної вставки таких пунктів меню як File, Edit, Tools, і Help.

Елемент управління ContextMenuStrip

Новий клас ContextMenuStrip (System.Windows.Forms.ContextMenuStrip) розташований в секції Menus & Toolbars панелі інструментів Toolbox, є похідним від класу ToolStripDropDown і замінює застарілий традиційний клас ContextMenu. Цей клас працює приблизно так само, як і традиційний клас ContextMenu. Ви конструюєте ContextMenuStrip і призначаєте його властивості ContextMenuStrip якого-небудь елементу управління. Коли користувач натисне праву кнопку миші на цьому елементі управління, з'явиться контекстне меню у вигляді елементу ContextMenuStrip.

Page 109: метуказлабраб ооп 2011укр

109

Лабораторна робота №9. Виведення графічної інформації. GDI+.

Мета роботи: засвоїти основний механізм малювання з допомогою GDI+, властивості і методи класів простору імен System.Drawing, набути практичних навичок розробки застосувань з виведенням графічної інформації.

Варіанти завдання.

1. Розробити застосування «Аналоговий годинник». Використовувати класи Rectangle,

LinearGradientBrush, Color, SolidBrush, Font, Graphics, метод TranslateTransform класу Graphics, перелік ControlStyles. Інформацію про класи і структури узяти з MSDN.

2. Розробити застосування «Світлофор». Використовувати класи TextBox, System.Windows.Forms.Timer, System.String, структуру DateTime. Інформацію про класи і структури узяти з MSDN.

Хід роботи.

1. Виконати Вправу 1.

2. Виконати Вправу 2.

3. Виконати Вправу 3.

4. Виконати завдання згідно своєму варіанту.

Page 110: метуказлабраб ооп 2011укр

110

Вправа 1. Виведення ліній за допомогою класу Pen.

Ми малюватимемо лінії за допомогою класу Pen, що визначає колір, товщину і зразок лінії, яка малюється програмою. Призначення властивостей Color (колір) і Width (товщина) очевидні, а зразок дозволяє визначати, чи потрібно намалювати суцільну лінію або лінію, що складається з рисок і крапок.

Запустіть Visual Studio 2005 і створіть нове C# Windows Application. При створенні нового проекту Visual Studio 2005 створює також і нову порожню форму для цього проекту, яка одержує ім'я Form1. У модулі Form1.cs міститься код, призначений для цієї форми. Клацніть на формі правою кнопкою миші і виберіть пункт View Code з меню, що відкрилося. Як альтернатива можна клацнути правою кнопкою миші на Form1.cs у Solution Explorer, щоб вибрати пункт View Code з меню, що відкрилося. Додайте в Form1.cs наступний код:

protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; using (Pen blackPen = new Pen(Color.Black, 1)) { for (int у = 0; у < ClientRectangle.Height; у += ClientRectangle.Height/10) { g.DrawLine(blackPen, new Point(0,0), new Point(ClientRectangle.Width,y)); } } }

Тепер натисніть F5 і запустіть програму.

Вправа 2. Малювання фігур за допомогою класу Brush

Наступний приклад присвячений використанню класу Brush (кисть) для малювання різних фігур, таких як прямокутники, еліпси, сектори і багатокутники. Клас Brush – це абстрактний клас. Для створення об'єктів ми використовуватимемо класи, похідні від класу Brush, такі як SolidBrush, TextureBrush і LinearGradientBrush. Клас Brush знаходиться в просторі імен System.Drawing. Класи TextureBrush і LinearGradientBrush знаходяться в просторі імен System.Drawing.Drawing2D. Ось що дозволяє робити кожний з цих класів:

• SolidBrush заповнює фігуру суцільним кольором.

• TextureBrush дозволяє заповнювати фігуру малюнком, що зберігається в двійковому представленні. При створенні такої кисті потрібно також задавати обрамляючий прямокутник і режим обрамлення. Обрамляючий прямокутник визначає, яку порцію малюнка ми повинні використовувати при малюванні, - використовувати весь малюнок цілком абсолютно необов'язково. Для режиму обрамлення існує декілька можливостей, включаючи Tile (черепиця) – TileFlipX, TileFlipY та TileFlipXY, що дозволяють послідовно розбивати зображення на окремі квадрати. За допомогою TextureBrush можна створювати дуже цікаві і вельми вражаючі ефекти.

• LinearGradientBrush містить кисть, яка дозволяє малювати плавний перехід від одного кольору до іншого, причому перший колір переходить в другій під певним кутом. Кути при цьому задаються в градусах. Кут, рівний 0”, означає, що перехід від одного кольору до іншого здійснюється зліва направо. Кут, рівний 90”, означає, що перехід від одного кольору до іншого здійснюється зверху вниз.

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

Запустіть Visual Studio 2005 і створіть нове C# Windows Application. Клацніть на формі правою кнопкою миші і виберіть пункт View Code з меню, що відкрилося. Знайдіть конструктор класу

Page 111: метуказлабраб ооп 2011укр

111

Form1 і додайте в нього звернення до методу SetStyle() відразу за зверненням до методу InitializeComponent(). SetStyle() – це функція класу Form. Видозмінений конструктор виглядатиме таким чином:

public Form1() { // // Необхідно для підтримки Windows Form Designer //

InitializeComponent(); SetStyle(ControlStyles.Opaque, true); // Слід зробити. Будь-який код, що відноситься до конструктора // повинен бути поміщений після виклику методу InitializeComponent(). // }

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

У самий початок файлу ми включимо рядок з оператором using, оскільки в даному прикладі ми використовуватимемо клас LinearGradientBrush, який знаходиться в просторі імен Drawing2D. Після додавання директивою using простору імен Drawing2D, код прийме наступний вигляд:

using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data;

Тепер необхідно додати до нашого класу метод OnPaint():

protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.FillRectangle(Brushes.White, ClientRectangle); g.FillRectangle(Brushes.Red, new Rectangle(10, 10, 50, 50)); Brush linearGradientBrush = new LinearGradientBrush( new Rectangle(10, 60, 50, 50), Color.Blue, Color.White, 45); g.FillRectangle(linearGradientBrush, new Rectangle(10, 60, 50, 50)); // Викликаємо метод Dispose() уручну linearGradientBrush.Dispose(); g.FillEllipse(Brushes.Aquamarine, new Rectangle(60, 20, 50, 30)); g.FillPie(Brushes.Chartreuse, new Rectangle(60, 60, 50, 50), 90, 210); g.FillPolygon(Brushes.BlueViolet, new Point[]{

new Point(110, 10) new Point(150, 10) new Point(160, 40) new Point(120, 20) new Point(120, 60) ));

}

Тепер натисніть клавішу F5 і запустіть програму.

Page 112: метуказлабраб ооп 2011укр

112

Вправа 3. Малювання квадратів по натисненню лівої кнопки миші

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

Мал. 13. Застосування, що малює квадрати

Запустіть Visual Studio 2005 і створіть нове C# Windows Application, назвавши його DrawSquare. Виділіть форму і змініть її властивість Text на “DrawSquare”.

Помістіть на форму елемент управління StatusStrip, який забезпечуватиме функціональність рядка стану. (У старих версіях Visual Studio для цих цілей використовувався компонент StatusBar.) Клацніть на стрілці в лівій частині компоненту StatusStrip і виберіть із списку Status Label. У вашому проекті з'явиться об'єкт toolStripStatusLabel1, у властивості якого Text можна виводити повідомлення в рядок стану.

Виділіть форму. У вікні Properties перейдіть на закладку Events і створіть обробник події MouseDown. Перед цим обробником вставте рядок з визначенням об'єкту типу ArrayList для зберігання квадратів, які створюватимуться по клацанню лівої кнопки миші.

// Store the squares that are painted on the form. ArrayList squares = new ArrayList();

До групи команд, що починаються з using, додайте рядок:

using System.Collections;

Напишіть обробник події MouseDown в наступному вигляді:

private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { // Add а square and update the screen. Rectangle square = new Rectangle(e.X, e.Y, 20, 20); squares.Add(square); this.Invalidate(square); } else if (e.Button == MouseButtons.Right) { // Search for the clicked square. int squareNumber = 0; foreach (Rectangle square in squares)

Page 113: метуказлабраб ооп 2011укр

113

{ squareNumber++; if (square.Contains(e.X, e.Y)) { MessageBox.Show("Point inside square #" + squareNumber.ToString()); } } } }

Перед обробником події MouseDown вставте наступний метод:

private void DrawRectangle(Rectangle rect, Graphics g) { Pen drawingPen = new Pen(Color.Black, 2); g.DrawRectangle(drawingPen, rect);

}

Створіть обробник події Paint.

private void Form1_Paint(object sender, PaintEventArgs e) { Pen drawingPen = new Pen(Color.Black, 2); foreach (Rectangle square in squares) { e.Graphics.DrawRectangle(drawingPen, square); } toolStripStatusLabel1.Text = " " + squares.Count.ToString() + " squares";

}

Запустіть і протестуйте застосування.

Методичні вказівки і теоретичні відомості.

GDI розшифровується як Graphic Device Interface (інтерфейс графічних пристроїв). GDI+ - це бібліотека, покликана замінити існуючий інтерфейс GDI, що є графічним ядром попередніх версій Windows. Вона поєднує в собі всі достоїнства свого попередника і надає безліч нових могутніх можливостей. Саме ця бібліотека, вірніше, заснований на ній новий графічний інтерфейс, є "обличчям" нових операційних систем – Windows XP і Windows 2003 Server.

У .NET передбачено ряд просторів імен, призначених для підтримки GDI+. Крім очікуваних стандартних типів (наприклад, для роботи з кольором, з шрифтами, з пером і кистю, із зображеннями) в цих просторах імен передбачені типи для виконання досить витончених операцій, таких як геометричні перетворення, згладжування нерівностей, підготовка палітри, підтримка виведення на принтер і багато інших. Перелік найбільш важливих просторів імен для роботи з графічними зображеннями представленв таблиці 10.

Таблиця 10. Найбільш важливі простори імен GDI+.

Простір імен Спеціалізація System.Drawing Це – найважливіший простір імен GDI+, який містить

основні типи для виведення графіки (для роботи з шрифтами, перами, кистю і т.п.), а також виключно важливий тип Graphics.

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

System.Drawing.Imaging Тут визначені типи, які дозволяють безпосередньо працювати з графічними зображеннями (міняти палітру, витягувати метадані зображень, виконувати операції з метафайлами і т.п.)

Page 114: метуказлабраб ооп 2011укр

114

System.Drawing.Printing Цей простір імен визначає типи для виведення графіки на принтер і взаємодії з принтером в цілому.

System.Drawing.Text Цей простір імен дозволяє працювати з системними шрифтами.

Нові технології і можливості GDI+:

• Градієнтне зафарбовування: дозволяє заливати складні фігури відтінками з різними законами розподілу кольору, малювати векторні примітиви (наприклад, лінії) з градієнтним забарвленням.

• Підтримка прозорості: можна створювати кисті і растри з прозорими і напівпрозорими областями, заливати області напівпрозорим кольором, призначати Color Key для растрового зображення і працювати з його каналом альфа, а також малювати напівпрозорі векторні примітиви і текст.

• Режими поліпшення зображення: дозволяють значно поліпшити призначене для користувача сприйняття за рахунок згладжування контурних нерівностей (antialiasing) і префильтрации растрових зображень.

• Сплайни: окрім тих, що вже існують в GDI кривих Безье, підтримується новий вигляд кривих - сплайни, які імітують поведінку натягнутої і зігнутої сталевої смуги. Сплайни є гладкими кривими.

• Шляхи: як вже говорилося, шляхи тепер існують незалежно від контексту малювання і є могутнім засобом створення складних векторних об'єктів. Крім того, з'явилася можливість вирівнювати (flatten) шляхи, тобто перетворювати їх до набору відрізків прямих.

• Координатні перетворення: об'єкт Matrix дозволяє здійснювати операції повороту, перенесення, масштабування і віддзеркалення об'єктів GDI+.

• Регіони: на відміну від GDI, регіони тепер не прив'язані до координат пристрою і підкоряються координатним перетворенням.

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

• Підтримка популярних форматів графічних файлів: незвичайно приємне нововведення для всіх програмістів, що мають справу з різними графічними форматами. Підтримуються формати BMP, GIF, TIFF, JPEG, Exif (розширення TIFF і JPEG для цифрових фотокамер), PNG, ICON, WMF і EMF. Декодери різних форматів виконані з урахуванням їх специфіки, так що Ви зможете, наприклад, відобразити анімаційний GIF або додати коментар до TIFF-файлу. Завантажений, створений або модифікований файл може бути збережений на диск в одному з відповідних форматів. Існує можливість написання власних декодерів.

• Формат EMF+: зрозуміло, вся ця пишність не могла уміщатися в тісні рамки старого Enhanced Metafile. Для опису нових можливостей був створений новий формат метафайлу EMF+, який дозволяє зберегти на диск і потім програти послідовність графічних команд. Існує можливість записати "дуальний" метафайл, зрозумілий старим GDI-програмам. Нові програми читатимуть з нього GDI+ - інформацію.

Page 115: метуказлабраб ооп 2011укр

115

Огляд простору імен System.Drawing

Більшість типів, які ви використовуватимете при створенні застосувань GDI+, знаходяться в просторі імен System.Drawing. У таблиці 11 показані основні типи цього простору імен.

Таблиця 11. Основні типи простору імен System.Drawing

Тип Призначення

Bitmap Інкапсулює файл зображень (*.bmp та інші)

Brush Brushes SolidBrush SystemBrushes TextureBrush

Об'єкти Brush (кисть)використовуються для заповнення простору усередині геометричних фігур, таких як прямокутники, еліпси і полігони.

BufferedGraphics Цей новий .NET 2.0 тип забезпечує подвійну буферизацію, яка використовується для зменшення мерехтіння при перемальовуванні.

Color SystemColors

Структура Color визначає набір статичних полів, які можуть бути використані для настройки кольору пер та кистей.

Font FontFamily

Тип Font інкапсулює характеристики шрифту.

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

Icon SystemIcons

Ці класи призначені для роботи з призначеними для користувача і системними піктограмами.

Image ImageAnimator

Image – це абстрактний базовий клас, який забезпечує можливості типів Bitmap, Icon і Cursor.

Pen Pens SystemPens

Pen (перо) використовується для малювання прямих і кривих ліній.

Point PointF

Ці структури представляють (x,y) координати точок у вигляді цілих або дійсних чисел.

Rectangle RectangleF

Ці структури призначені для роботи з прямокутними областями (int/float).

Size SizeF

Ці структури забезпечують роботу з розмірами (висотою і шириною).

StringFormat Цей тип використовується для форматування тексту.

Region Визначає область, зайняту геометричною фігурою.

Можливості класу Graphics

Клас System.Drawing.Graphics – це ворота у функціональні можливості малювання GDI+. Цей клас не тільки представляє поверхню, на якій ви хочете малювати (це може бути поверхня форми, поверхні елементів управління або регіони пам'яті), але також визначає набір методів, які дозволяють виводити текст, зображення і геометричні фігури. Найбільш часто використовувані методи цього класу представлені в таблиці 12.

Page 116: метуказлабраб ооп 2011укр

116

Таблиця 12. Деякі методи класу Graphics.

Метод Призначення

FromHdc() FromHwnd() FromImage()

Ці статичні методи забезпечують можливість отримання об'єкту Graphics з елементу управління або зображення.

Clear() Заповнює об'єкт Graphics вибраним користувачем кольором, видаляючи його попередній вміст.

DrawArc() DrawBezier() DrawBeziers() DrawCurve() DrawEllipse() DrawIcon() DrawLine() DrawLines() DrawPie() DrawPath() DrawRectangle() DrawRectangles() DrawString()

Ці методи використовуються для виведення зображень і геометричних фігур. Як ви побачите, методи DrawXXX() використовують об'єкт GDI+ Pen.

FillEllipse() FillPath() FillPie() FillPolygon() FillRectangle()

Ці методи використовуються для заповнення внутрішніх областей графічних об'єктів

Об'єкт Graphics для деякого вікна можна одержати двома шляхами. Перший полягає в перевизначенні події OnPaint() – віртуального методу, який клас Forms успадковує від класу Control. В цьому випадку об'єкт Graphics ми одержуємо з PaintEventArgs, який передається разом з подією:

protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; // Малюємо тут

}

У деяких ситуаціях може потрібно виконувати малювання у вікні безпосередньо, не чекаючи настання події OnPaint(). Це може виявитися актуальним в тому випадку, якщо ми створюємо код, призначений для вибору у вікні яких-небудь графічних об'єктів, або переносимо якийсь об'єкт за допомогою миші. В цьому випадку доступ до об'єкту Graphics можна одержати, звертаючись до методу CreateGraphics() даної форми, який є ще одним методом, успадкованим класом Forms від класу Control.

protected void Form1_Click(object sender, System.EventArgs e) { Graphics g = this.CreateGraphics();

// Малюємо тут

g.Dispose(); }

Page 117: метуказлабраб ооп 2011укр

117

Лабораторна робота №10. Доступ до даних за допомогою ADO.NET.

Мета роботи: засвоїти основний механізм доступу до даних за допомогою ADO.NET, набути практичних навичок розробки застосувань, що відображають інформацію з базы даних.

Завдання.

Для бази даних Northwind Traders, що входить в поставку Visual Studio 2005, виконати наступне:

1. Створити з'єднання з базою даних з використанням Data Source Configuration Wizard.

2. Витягнути дані з бази даних і відобразити їх графічно в Microsoft Visual Studio 2005.

3. Провести вибірку з бази даних SQL Server, використовуючи ADO.NET.

Хід роботи.

1. Створення бази даних. Перш, ніж просуватися далі, треба створити базу даних Northwind Traders. Запустіть Far і перейдіть в каталог . . . \Program Files\Visual Studio 8\SDK\v2.0\Samples\Setup\

2. У командному рядку наберіть наступну команду:

sqlcmd –S YourServer\SQLExpress –E –iinstnwnd.sql

Замініть YourServer на ім'я свого комп'ютера. (Ви можете визначити ім'я комп'ютера, набравши в командному рядку команду hostname). Ця команда використовує утиліту sqlcmd

для з'єднання з локальною версією SQL Server 2005 Express і запуску скрипта instnwnd.sql. Цей скрипт містить команди SQL, які створюють базу даних Northwind Traders і таблиці бази даних, і заповнюють таблиці деякою тестовою інформацією.

3. Створення джерела даних (data source). Використовуючи Visual Studio 2005, створіть новий проект на базі шаблону Windows Application. Назвіть проект DisplayProducts і збережіть його в своєму робочому каталозі.

4. У меню Data виберіть Add New Data Source. Запуститься майстер Data Source Configuration Wizard. Ви використовуєте цей майстер для створення з'єднання з джерелом даних. Джерелом даних може бути база даних (Database), об'єкт (Object), або web-сервіс (Web Service).

5. Виберіть Database і клацніть Next. Наступна сторінка майстра запрошуємо вас надати інформацію про з'єднання, яке ви хочете використовувати. Ви ще не створювали жодного з'єднання, тому клацніть кнопку New Connection.

З'явиться діалог Choose Data Source, що дозволяє вам вибрати Data source і Data provider. Data source уточнює тип бази даних, а Data provider уточнює спосіб з'єднання з базою даних.

6. Для даного застосування виберіть Microsoft SQL Server як Data source і .NET Framework Data Provider for SQL Server як Data provider. Клацніть Continue для переходу до наступного кроку.

З'явиться діалог Add Connection. У цьому діалозі ви уточните, з яким SQL Server ви хочете з'єднатися, механізм аутентифікації і вкажіть базу даних, яку ви хочете використовувати.

7. Наберіть YourServer\SQLExpress у полі Server name, де YourServer – це ім'я вашого комп'ютера. Виберіть опцію Use Windows Authentication в групі радіокнопок Log on to the server. Виберіть в комбінованому списку базу даних Northwind і потім клацніть OK.

Page 118: метуказлабраб ооп 2011укр

118

Ви повернетеся в майстер Data Source Configuration Wizard. Нове з'єднання одержить ім'я YourServer\SQLExpress.Northwind.dbo.

8. Клацніть знак + зліва від напису Connection String. Ви побачите рядок, який містить деталі з'єднання. Ця інформація представляється у форматі, який може використовувати SQL Server provider для з'єднання до сервера.

9. Клацніть Next.

Інформація про з'єднання, яке ви визначили, також може бути збережена в конфігураційному файлі. Збережіть інформацію, використовуючи ім'я за умовчанням.

10. Клацніть Next.

Наступна сторінка майстра дозволяє вам вибрати дані, які ви хочете використовувати.

11. Розверніть директорію Tables і виберіть таблиці Products (Продукти) і Suppliers (Постачальники).

Майстер згенерує об'єкт DataSet з ім'ям NorthwindDataSet, яким ви можете управляти. Об'єкт DataSet представляє копію в пам'яті таблиць і рядків, витягнутих з бази даних.

12. Клацніть Finish, щоб закінчити роботу з майстром.

13. Проглядання інформації про продукти і постачальників. У меню Data клацніть Preview Data.

З'явиться діалог Preview Data, що дає вам можливість проглянути дані, що повертаються створеним вами джерелом даних (Якщо у вас немає пункту меню Preview Data, виконайте подвійне клацання на Form1.cs у Solution Explorer, щоб відобразити Form1 у вікні Design View).

14. Клацніть на випадному списку Select an object to preview.

Ви побачите представлений у вигляді дерева вміст NorthwindDataSet.. Об'єкт DataSet містить два об'єкти DataTable з іменами Products і Suppliers. Нижче за кожне DataTable ви побачите вузол з ім'ям Fill, GetData(). Ці вузли відповідають об'єктам типу TableAdapter.

15. Клацніть вузол Fill, GetData() під пунктом Products і потім клацніть кнопку Preview.

У вікні з'являться рядки з таблиці Products бази даних.

16. У випадному списку Select an object to preview клацніть вузол Fill, GetData() під Suppliers. Клацніть Preview.

Цього разу відобразяться дані з таблиці Suppliers.

17. Клацніть Close, щоб закрити діалог Preview Data.

18. Відображення даних в застосуванні. Після того, як ви побачили, які визначені об'єкти DataSets, розглянемо, як ви можете їх використовувати в застосуванні.

У Solution Explorer клацніть праву кнопку миші на Form1.cs і перейменуйте форму в DataForm.cs. Діалогове вікно, що з'явилося, запитає, чи хочете ви модифікувати всі посилання з урахуванням нового імені. Клацніть Yes.

19. Виділіть DataForm у вікні Designer View. Використовуючи вікно Properties, властивості Text привласніть значення Suppliers and Products і змініть властивість Size на 800, 410.

Page 119: метуказлабраб ооп 2011укр

119

20. У меню Data виберіть Show Data Sources. З'явиться вікно Data Sources, що відображає NorthwindDataSet з таблицями Products і Suppliers. Розверніть ці таблиці.

З'являться стовпці кожної таблиці разом з піктограмами, що показують, як кожен стовпець відображатимемося на формі. Більшість стовпців треба відображати в елементі textbox, за винятком стовпця Discontinued в таблиці Products, для якого потрібен checkbox. Це через те, що цей стовпець представляє бітове поле, що приймає логічне значення True/False. Також відзначте для себе, що Products з'являється двічі: як об'єкт DataTable і як стовпець в таблиці Suppliers. Так виявляється зв'язок між цими таблицями.

21. Клацніть таблицю Suppliers. З'явиться випадне меню, виберіть в ньому Details.

Ця дія встановить представлення таблиці постачальників у вигляді множини полів замість уявлення в елементі DataGrid. Представлення Details треба використовувати для даних на стороні “one” відносно багато-до-одного (many-to-one), а представлення Grid view зручно для сторони “many”.

22. Клацніть SupplierID в таблиці Suppliers. З'явиться інше випадне меню. Клацніть його. Ви побачите різні способи для представлення даних в цьому стовпці. Стовпець SupplierID є первинний ключ для таблиці Suppliers, тому його не можна змінювати. З цієї причини виберіть для нього представлення Label.

23. Клацніть таблицю Suppliers і перетягніть її в лівий верхній кут форми Suppliers and Products.

Відмітьте, що під формою з'явиться ряд компонентів.

Компонент Опис

northwindDataSet Це джерело даних, використовуване формою. Компонент має в своєму розпорядженні методи оновлення даних в базі даних.

suppliersBindingSource Цей компонент діє як посередник між елементами управління на формі і джерелом даних. Він має в своєму розпорядженні методи навігації по DataSet, додаваннях, видаленнях і редагуваннях рядків.

suppliersTableAdapter Це об'єкт TableAdapter для таблиці Suppliers, що має в своєму розпорядженні методи пошуку рядків в таблиці і поповнення таблиці.

suppliersBindingNavigator Це елемент BindingNavigator, що надає стандартний механізм для навігації по рядках таблиці

24. Клацніть на таблиці Products, яка розташовується усередині таблиці Suppliers, і перетягніть її на форму праворуч від полів таблиці Suppliers.

На формі з'явиться компонент DataGridView. Відмітьте, що під формою з'являться ще два компоненти: productsBindingSource і компонент TableAdapter для таблиці продуктів.

25. Виділіть компонент DataGridView на формі і розтягніть його направо до правої межі форми.

26. Припускаючи, що компонент DataGridView як і раніше виділений, клацніть Smart Tag handle, розташований на вершині правого верхнього кута компоненту.

З'явиться діалог DataGridView Tasks. Ви можете використовувати цей діалог для швидкої зміни деяких властивостей компоненту DataGridView і виконувати деякі інші завдання.

Page 120: метуказлабраб ооп 2011укр

120

Очистіть чекбоксы Enable Adding, Enable Editing, Enable Deleting, і Enable Column Reordering.

27. Запустіть застосування без відладки, вибравши в меню Debug пункт Start Without Debugging. Коли з'явиться форма, перший постачальник (Exotic Liquids) відобразиться разом з трьома продуктами, які він поставляє. Клацніть на кнопці Move next на панелі навігації. З'явиться інформація про наступного постачальника.

28. Закрийте форму і поверніться в Visual Studio 2005.

Короткі теоретичні відомості.

Коротка історія забезпечення доступу до даних

Коли були створені найперші бази даних, такі як Oracle і DB2 компанії IBM, кожному розробнику, якому був потрібен доступ до даних, що зберігаються в них, доводилося використовувати функції, специфічні для конкретної бази даних. Кожна система володіла власною бібліотекою функцій, наприклад, для Oracle використовувався Oracle Call Interface, а для SQL Server компанії SyBase (пізніше купленої компанією Microsoft) – бібліотека DBLib. Це забезпечувало швидкий доступ до даних, оскільки програми з цих бібліотек працювали з БД безпосередньо. З іншого боку, це означало, що програмісти повинні бути знайомі з бібліотеками для кожної БД, з якими їм доводилося працювати, тому завдання написання застосувань для роботи з даними було вельми складне. Це також означало, що якщо компанія переходила на використання іншої БД, застосування доводилося переписувати наново.

Ця проблема була вирішена за допомогою Open Database Connectivity (ODBC – відкрита система зв'язку з базами даних). Система ODBC була створена на початку 90-х рр. компанією Microsoft спільно з поряд інших компаній і була стандартним набором функцій, які розробники могли застосовувати при роботі з будь-якими базами даних. Ці функції транслювалися у виклики функцій, властивих конкретній базі даних, за допомогою драйверів, специфічних для цієї бази даних.

Це дозволило вирішити основні проблеми, викликані існуванням різних бібліотек баз даннях, – розробникам тепер потрібно було уміти користуватися тільки одним набором функцій (функціями ODBC), і якщо компанія переходила від однієї БД до іншої, то все, що їм доводилося змінювати, – це код, що відповідає за встановлення з'єднання з базою даних. При цьому одна проблема все одно залишалася невирішеною. У компаній скопилася величезна кількість представлених в електронному вигляді даних, що зберігаються в найрізноманітніших формах, – у вигляді електронних листів, web-сторінок і т.п. ODBC чудово працювала з даними в традиційних базах даних, але не справлялася з іншими типами даних, які не зберігалися у вигляді акуратних стовпців і рядків і у яких могла бути відсутньою яка-небудь зв'язна структура.

Рішення цієї проблеми привело до появи OLE DB. OLE DB працює аналогічно ODBC, представляючи рівень абстракції між БД і застосуваннями, яким потрібен доступ до даних. Клієнтські застосування взаємодіють з джерелом даних, яке може бути традиційною базою даних або будь-яким іншим сховищем інформації, за допомогою провайдера OLE DB для цього джерела. Дані, витягувані з джерела, представляються в застосуванні в табличному форматі – тобто так, як ніби вони були витягнуті з бази даних.

Остання технологія доступу до даних, про яку необхідно згадати, – це ActiveX Data Objects (ADO). ADO – це просто тонкий шар, який знаходиться над OLE DB і дозволяє програмам, написаним на мовах високого рівня на зразок Visual Basic, діставати доступ до даних OLE DB.

Page 121: метуказлабраб ооп 2011укр

121

Введення в ADO.NET

З приходом .NET Framework, Microsoft вирішила модернізувати свою модель доступу до баз даних, ActiveX Data Objects (ADO), і створила ADO.NET.

ADO.NET складається з набору об'єктів, що знаходяться в просторі імен System.Data, які взаємодіють з базами даних за допомогою провайдерів даних .NET. Об'єкти ADO.NET дозволяють встановлювати з'єднання з базами даних, а також витягувати, редагувати, знищувати і вставляти дані в бази даних і, крім того, здійснювати маніпуляції з даними програмним шляхом.

Провайдери даних .NET

ADO.NET складається з двох фундаментальних частин – об'єкту DataSet і провайдера даних .NET. Об'єкт DataSet використовується для того, щоб зберігати в програмі набір даних, представлених в табличному вигляді; при цьому абсолютно байдуже, звідки поступили ці дані. Провайдер даних складається з набору компонентів, специфічних для конкретного джерела даних, які дозволяють встановлювати з'єднання і здійснювати взаємодію з цим джерелом. Кожен провайдер знаходиться у власному просторі імен в рамках простору імен System.Data. Існує чотири доступні провайдери даних:

o Провайдер даних для SQL Server. Він знаходиться в просторі імен System.Data.SqlClient.

o Провайдер даних для Oracle. Він знаходиться в просторі імен System.Data.Oracle. o Провайдер даних для OLE DB. Він використовується для встановлення з'єднання з

джерелом даних за допомогою OLE DB і знаходиться в просторі імен System.Data.OleDb.

o Провайдер даних для ODBC. Він може використовуватися для встановлення з'єднання з базами даних, що володіють драйверами ODBC. Провайдер даних ODBC знаходиться в просторі імен System.Data.Odbc.

Провайдери даних складаються з чотирьох основних частин, описаних в наступній таблиці:

Таблиця 13. Складові частини провайдерів даних.

Ім'я компоненту

Опис

Connection Використовується для встановлення з'єднання з БД або яким-небудь іншим джерелом даних

Command Використовується для витягання, редагування, знищення і включення даних в базу даних

DataReader Забезпечує потік даних з джерела даних. DataAdapter Використовується для наповнення DataSet даними з джерела даних, а

також для оновлення джерела даних при внесенні будь-яких змін в DataSet.

При використанні цих об'єктів не відбувається звернення до ним по цих іменах. Кожен провайдер володіє своєю власною реалізацією цих класів, і, оскільки в класах кожного провайдера реалізовані однакові інтерфейси, вони всі володіють одними і тими ж методами і властивостями. Наприклад, якщо потрібно встановити з'єднання з базою даних SQL Server, то для цих цілей використовується об'єкт SqlConnection, а при необхідності з'єднання з джерелом даних ODBC – об'єкт OdbcConnection. У обох об'єктах реалізується інтерфейс IDbConnection, тому вони володіють одним і тим же набором методів і властивостей.

Page 122: метуказлабраб ооп 2011укр

122

Об'єкт DataSet

Після встановлення з'єднання з БД і отримання даних з неї надається можливість виконувати різні маніпуляції над даними за допомогою об'єкту DataSet, що є сімейством об'єктів DataTable (таблиця даних). Об'єкт DataTable дозволяє зберігати дані в табличному вигляді, тобто у вигляді стовпців і рядків. Об'єкт DataSet не є складовою частиною провайдера даних (існує тільки один тип об'єкту DataSet незалежно від того, поступили дані з джерела даних SQL Server або OLE DB), отже, об'єкт DataSet не відповідає за встановлення з'єднання з джерелом. Це означає, що коли ми виконуємо які-небудь маніпуляції над даними, що знаходяться в DataSet, то ми насправді працюємо всього лише з копією цих даних, розташованих в пам'яті локального комп'ютера. Це дозволяє зменшити навантаження на сервер і на мережу, оскільки встановлення з'єднання з джерелом даних відбувається тільки у момент первинного звернення до даних і тоді, коли ми завершуємо їх редагування і необхідно внести зроблені зміни в саму базу даних. Разом з перевагами, така архітектура роботи без встановленого з'єднання приводить до виникнення певних проблем. У середовищі з повністю розірваним з'єднанням користувач не може бути повідомлений про зміни, які були внесені в дані іншими користувачами.

Page 123: метуказлабраб ооп 2011укр

123

Лабораторна робота №11. Застосування ASP.NET .

Мета роботи: засвоїти основи web-програмування з використанням ASP.NET, набути практичних навичок розробки web-застосувань.

Завдання.

Розробити свою домашню web-сторінку, використовуючи технологію ASP.NET..

Хід роботи.

1. Виконати Вправу.

2. Виконати завдання.

Вправа.

У цій вправі ви створите просте застосування ASP.NET, яке використовує серверні елементи управління (Server controls) для введення відомостей про службовців вигаданої компанії, що займається програмним забезпеченням. В процесі розробки ви ознайомитеся із структурою типового Web застосування.

Зауваження.

Ви не повинні обов'язково запускати IIS на вашому комп'ютері, щоб розробляти Web

застосування. Visual Studio 2005 має свій власний Development Web server. Коли ви

розробите і запустите Web застосування, за умовчанням Visual Studio 2005 запустить

застосування, використовуючи цей сервер. Проте, після остаточної розробки і

тестування Web застосування, треба як і раніше використовувати IIS для хостингу.

1. Запустіть Visual Studio 2005. У меню File виберіть New, а потім виберіть Web Site.

З'явиться діалог New Web Site.

2. Виділіть шаблон ASP.NET Web Site. У списку Location виберіть File System і, використовуючи кнопку Browse, виберіть робочий каталог, в якому розташовуватиметься ваш сайт. У списку Language виберіть Visual C# і клацніть OK.

Зауваження. Установка в полі Location значення FileSystem орієнтована на використання Development Web server. Ви можете в полі Location вибрати IIS і задати URL, по якому розташовуватиметься ваш сайт.

Створене застосування складатиметься з теки Web Folder з ім'ям App_Data і форми Web form з ім'ям Default.aspx. У вікні Source View з'явиться HTML код для сторінки за умовчанням.

3. У Solution Explorer виберіть файл Default.aspx. У вікні Properties зміните ім'я файлу на EmployeeForm.aspx.

4. Клацніть кнопку Design внизу форми, щоб перейти в режим Design View. Вікно Design View буде на даний момент порожнім.

У вікні Design View ви можете перетягувати елементи з панелі Toolbox, і Visual Studio 2005 згенерує відповідний HTML код. Цей HTML код ви можете переглядати і редагувати у вікні Source View.

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

Page 124: метуказлабраб ооп 2011укр

124

5. Виділіть форму у вікні Design View. У вікні Properties зміните властивість Title об'єкту DOCUMENT на Employee Information.

Значення, яке ви задали у властивості Title, в рядку заголовка web браузера при завантаженні сторінки.

6. Виберіть властивість Style і клацніть овальну кнопку.

З'явиться діалогове вікно Style Builder. Цей діалог дає вам можливість створити стиль для форми. (Стиль визначає шрифт за умовчанням, колір, вирівнювання і інші елементи Web форми і її елементів.)

7. У секції Font Name упевніться, що вибрана опція Family, і клацніть кнопку справа. У діалозі Font Picker, що з'явився, виберіть Arial в списку Installed Fonts і клацніть >> для додавання його в список Selected Fonts. Клацніть OK для повернення в Style Builder.

8. У випадному списку Color виберіть Blue.

9. У лівій панеле діалогового вікна клацніть Background. Покажеться сторінка Background. Виберіть опцію Transparent.

10. Використовуючи провідник Windows, скопіюйте файл computer.gif з каталога лабораторних робіт курсу на сервері ВЦ2 в робочий каталог вашого сайту.

11. Поверніться в діалог Style Builder. У текстовому полі Image наберіть computer.gif. Клацніть OK.

На Web формі з'явиться зображення комп'ютера як background image.

12. Відкрийте панель Toolbox і переконайтеся, що розкрита категорія Standard.

13. Перетягніть з панелі Toolbox чотири елементи Label і три елементи TextBox на Web форму. Відмітьте, як елементи управління підхоплюють шрифт і колір, задані в стилі форми.

14. Використовуючи вікно Properties, встановіть властивості цих елементів згідно таблиці. Control Property Value

Label1 Font Bold (expand the Font property)

True

Font Name Arial Black

Font Size X-Large

Text Honest John Software Developers

Height 36 px

Page 125: метуказлабраб ооп 2011укр

125

Width 630 px

Label2 Text First Name

Label3 Text Last Name

Label4 Text Employee Id

TextBox1 Height 24 px

Width 230 px

(ID) firstName

TextBox2 Height 24 px

Width 230 px

(ID) lastName

TextBox2 Height 24 px

Width 100 px

(ID) employeeID

15. У вікні Design View виділите всі чотири елементи Label і три елементи TextBox (виділіть Label1, а потім всі інші, утримуючи клавішу Shift).

16. У меню Layout виберіть Position, а потім клацніть Absolute.

Ця установка дозволить вам перетягувати елементи форми на абсолютні позиції замість автоматичного вирівнювання.

17. Позиціонуйте написи і текстові поля так, як показано на малюнку.

18. Клацніть кнопку Source в нижній частині форми, щоб подивитися HTML код, відповідний формі.

19. Поверніться у вікно Design View.

20. У меню Layout виберіть Position і клацніть Auto-position Options. У діалозі Options розверніть вузол HTML Designer і клацніть CSS Positioning. На панеле справа виділите

Page 126: метуказлабраб ооп 2011укр

126

опцію “Change positioning to the following for controls added by using the Toolbox, paste, or drag and drop”и виберіть “Absolutely positioned” з випадного меню.

Ця дія дозволить вам надалі, при додаванні на форму нових елементів, вільно позиціонувати їх шляхом перетягання.

21. Додайте ще один елемент Label і чотири елементи RadioButton на Web форму. Встановіть властивості цих елементів згідно таблиці.

Control Property Value

Label5 Text Position

RadioButton1 Text Worker

TextAlign Left

GroupName positionGroup

Checked True

(ID) workerButton

RadioButton2 Text Boss

TextAlign Left

GroupName positionGroup

Checked False

(ID) bossButton

RadioButton3 Text Vice President

TextAlign Left

GroupName positionGroup

Checked False

(ID) vpButton

RadioButton1 Text President

TextAlign Left

GroupName positionGroup

Checked False

(ID) presidentButton

22. Позиціонуйте нові елементи на формі так, як показано на малюнку.

Page 127: метуказлабраб ооп 2011укр

127

23. Додайте ще один елемент Label і елемент DropDownList на Web форму. Встановіть властивості цих елементів згідно таблиці.

Control Property Value

Label6 Text Role

DropDownList1 Width 230 px

(ID) positionRole

Випадний список positionRole призначений для завдання різних посад працівникам усередині компанії. Ви повинні будете написати код, заповнюючий цей список динамічно.

24. Позиціонуйте нові елементи на формі так, як показано на малюнку.

25. Додайте дві кнопки Button і ще одну мітку Label на форму. Встановіть властивості цих елементів згідно таблиці.

Page 128: метуказлабраб ооп 2011укр

128

Control Property Value

Button1 Text Save

(ID) saveButton

Button1 Text positionRole

(ID) clearButton

Label7 Text leave blank

Height 48 px

Width 680 px

(ID) infoLabel

26. Позиціонуйте нові елементи на формі так, як показано на малюнку.

Ви повинні будете написати обробники натиснення на ці кнопки. По натисненню кнопки Save треба об'єднати інформацію, введену користувачем, і вивести її в InfoLabel. По натисненню кнопки Clear треба очистити текстові поля форми.

27. Тестування Web форми. У меню Debug клацніть Start Debugging.

Visual Studio 2005 побудує (build) застосування, запуститься Development Server ASP.NET, і далі запуститься Internet Explorer і відобразить форму.

Зауваження. Перший запуск Web застосування командою Start Debugging приведе до появи діалогу з повідомленням про те, що режим відладки неможливий. Ви можете або вибрати “Run without debugging”, або “Modify the Web.config file to enable debugging”, якщо ви дійсно ходите працювати в режимі відладки. Цей режим зручний, оскільки допускає установку крапок переривання (breakpoints) і покрокове виконання коду. Проте в режимі відладки сповільнюється виконання коду, і цей режим треба дезактивувати перед розгортанням застосування на сервері. Це можна зробити редагуванням файлу Web.config, шляхом видалення з нього рядка <compilation debug="true"/>.

Page 129: метуказлабраб ооп 2011укр

129

28. Закрийте Internet Explorer і поверніться в Visual Studio 2005.

Розуміння Server Controls

Елементи Web Forms, які ви додавали на форму, колективно називають серверними елементами управління – Server controls. Вони схожі на стандартні теги HTML, які ви можете бачити на звичайних Web сторінках. Проте Server controls є більш програмованими. Більшість Server controls можуть мати обробники подій, методи і властивості, які можуть бути запущеними на сервері.

Дослідження елементів Server controls.

29. У середовищі Visual Studio 2005 відкрийте файл EmployeeForm.aspx у вікні Source View.

30. Досліджуйте HTML код для форми. Відмітьте, що він містить визначення для кожного елементу управління. Подивіться на визначення для першої мітки Label детальніше.

<asp:Label ID="Label1" runat="server"

Text="Honest John Software Developers"

style="z-index: 100; left: 96px;

position: absolute; top: 24px"

Font-Bold="True" Font-Names="Arial Black"

Font-Size="X-Large" Height="36px" Width="630px">

</asp:Label>

Можна відмітити дві особливості. По-перше, подивіться на тип елементу – asp:Label. Всі елементи Web forms «живуть» в просторі імен “asp”. І, в других, елемент має атрибут runat="server". Цей атрибут говорить про те, що до елементу можна звернутися програмно за допомогою коду, запущеного на сервері.

31. Поверніться у вікно Design View.

Сторінці EmployeeForm.aspx потрібні декілька обробників подій: безліч обробників для заповнення випадного списку PositionRole, коли користувач вибирає посаду (Worker, Boss, Vice President, President); інший обробник для збереження інформації, коли користувач натиснув кнопку Save; і ще одинобработчик для очищення форми, коли користувач натиснув кнопку Clear. Ви зараз напишіть ці обробники.

Написання обробників подій.

32. У Solution Explorer розкрійте файл EmployeeForm.aspx.

З'явиться файл EmployeeForms.aspx.cs. Це файл, який дійсно міститиме код C# для обробників подій, які ви напишіть. Цей файл відомий як файл code-behind file. Ця особливість ASP.NET дозволяє вам відокремити код C# від логіки відображення Web застосування (ви можете фактично писати код C# для обробників у файл EmployeeForm.aspx, використовуючи вікно Source View, але такий підхід не рекомендується).

33. Відкрийте HTML код для EmployeeForm.aspx у вікні Source View. Досліджуйте перший рядок цього файлу. Вона виглядатиме приблизно так:

<%@ Page Language="C#" ... CodeFile="EmployeeForm.aspx.cs ... %>

Ця директива визначає файл, що містить початковий код для Web форми і мова, на якій він написаний.

34. У Solution Explorer виконаєте подвійне клацання на файлі EmployeeForm.aspx.cs.

Page 130: метуказлабраб ооп 2011укр

130

Файл відобразиться у вікні Code and Text Editor. На початку файлу поміщено декілька операторів using. Відмітьте, що цей файл посилено використовує простір імен System.Web і ряд його підпросторів – якраз там перебувають класи ASP.NET. Відмітьте також, що сам код міститься в класі _Default, похідному від System.Web.UI.Page; це клас, від якого успадковується весь Web Forms. Зараз він містить єдиний порожній метод з ім'ям Page_Load. Цей метод запускається при відображенні сторінки. Ви можете написати код в цьому методі для ініціалізації даних, необхідних для вашої форми.

35. Додайте метод з ім'ям initPositionRole в клас _Default після методу Page_Load.

private void initPositionRole()

{

}

Ви використовуватимете цей метод для ініціалізації випадного списку positionRole

значеннями за умовчанням

36. Додайте наступних операторів в метод initPositionRole:

positionRole.Items.Clear();

positionRole.Enabled = true;

positionRole.Items.Add("Analyst");

positionRole.Items.Add("Designer");

positionRole.Items.Add("Developer");

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

37. Додайте наступного оператора в метод Page_Load:

if (!IsPostBack)

{

initPositionRole();

}

Цей блок коду викликає заповнення списку positionRole при появі форми в клиенском браузере. Важливо зрозуміти, що метод Page_Load викликається кожного разу, як сервер посилає форму в браузер клієнта, а не тільки вперше. Наприклад, коли користувач клацає кнопку, форма посилається на Web-сервер для обробки; Web-сервер робить обробку і у відповідь посилає форму назад в Web браузер. Вам не потрібне, щоб ініціалізація виконувалася кожного разу, коли сторінка з'являється. Ви можете визначити, чи працює Page_Load метод перший раз, запрошуючи IsPostBack властивість веб-сторінки. Ця властивість повертає false, якщо сторінка відображається вперше, і true, якщо сторінка відновлюється, тому що користувач клацнув елемент управління. У коді, який ви додали, ви звертаєтеся до методу initPositionRole, тільки коли форма відображається вперше.

38. Перемкніться на файл EmployeeForm.aspx і перейдіть в режим Design View для форми. Виберіть радіо-кнопку workerButton. У вікні Properties клацніть кнопку Events. Виконайте подвійне клацання на події CheckedChanged. Ця подія відбувається, коли користувач клацнув радіо-кнопку, і її значення змінилося. Visual Studio 2005 згенерує метод workerButton_CheckedChanged для обробки цієї події.

39. Додайте в метод workerButton_CheckedChanged наступний оператор:

initPositionRole();

Page 131: метуказлабраб ооп 2011укр

131

Пам'ятайте, що значення за умовчанням для випадного списку positionRole такі ж, як для робочого (Worker), тому той же метод можна використовувати для ініціалізації списку.

40. Перемкніться на EmployeeForm.aspx у вікні Design View. Виберіть радіо-кнопку bossButton

і використайте вікно Properties для створення методу bossButton_CheckedChanged, події CheckedChanged, що є обробником. Додайте в метод bossButton_CheckedChanged наступні оператори:

positionRole.Items.Clear();

positionRole.Enabled = true;

positionRole.Items.Add("General Manager");

positionRole.Items.Add("Project Manager");

Це ті посади, які можен займати менеджер.

41. Перемкніться на EmployeeForm.aspx у вікні Design View і створіть обробник події CheckedChanged для радіо-кнопки vpButton (віце-президент). Додайте наступних операторів в цей метод:

positionRole.Items.Clear();

positionRole.Enabled = true;

positionRole.Items.Add("VP Sales");

positionRole.Items.Add("VP Marketing");

positionRole.Items.Add("VP Production");

positionRole.Items.Add("VP Human Resources");

42. Створіть завершальний обробник події CheckedChanged для радіо-кнопки President. Додайте наступний код в цей обробник:

positionRole.Items.Clear();

positionRole.Enabled = false;

Для президента компанії немає інших ролей, тому список радіо-кнопок робиться неактивним.

43. Створіть обробник події Click для кнопки Save. Звичайно цей метод використовується для збереження інформації в базі даних, але, щоб зробити це застосування простішим, цей метод буде просто відображати деякі введені дані в мітці InfoLabel. Додайте наступних операторів в метод saveButton_Click:

string position = "";

if (workerButton.Checked)

position = "Worker";

if (bossButton.Checked)

position = "Manager";

if (vpButton.Checked)

position = "Vice President";

if (presidentButton.Checked)

position = "President";

infoLabel.Text = "Employee:&nbsp" + firstName.Text + "&nbsp" +

lastName.Text + "&nbsp&nbsp&nbsp&nbspId&nbsp" +

employeeID.Text + "&nbsp&nbsp&nbsp&nbspPosition&nbsp" +

position;

Page 132: метуказлабраб ооп 2011укр

132

Символ &nbsp це перазрывный пропуск в HTML; звичайні пробільні символи полсе першого пропуску ігноруються браузером.

44. Створіть обробник події Click для кнопки Clear. Додайте наступних операторів в цей метод:

firstName.Text = "";

lastName.Text = "";

employeeID.Text = "";

workerButton.Checked = true;

initPositionRole();

infoLabel.Text = "";

Цей код очищає інформації, введену користувачем, і включає радіо-кнопку за умовчанням для ролей (Worker).

Нове тестування форми

45. Запустіть ваше застосування. Введіть прізвище службовця і його номер ID. Розкрійте випадний список ролей. З'явиться список ролей для робочого.

46. Змініть позицію в списку службовців на Vice President і знову розкрійте список ролей.

Ви відмітите, що список ролей не змінився, він як і раніше відображає ролі для робочого. Це трапилося через те, що обробник події CheckedChanged для кнопки Vice President не спрацював.

47. Закрийте Internet Explorer і знову перейдіть в програмне середовище Visual Studio 2005.

48. Відкрийте EmployeeForm.aspx у вікні Design View і виділите радіо-кнопку worker-Button. У вікні Properties встановите властивість AutoPostBack в True.

Коли користувач клацне цю радіо-кнопку, форма буде послана на сервер для обробки, спрацює обробник події CheckedChanged, і форма може бути модифікована, і відображатиме ролі для цієї радіо-кнопки. За умовчанням властивість AutoPostBack

встановлена в False, щоб уникнути непотрібного мережевого трафіку.

Встановіть властивість AutoPostBack в True і для інших радіо-кнопок: bossButton, vpButton, і presidentButton.

49. Знов запустите ваше застосування.

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

50. У меню View Internet Explorer клацніть Source для відображення початкового коду HTML цієї сторінки.

Запуститься Notepad для відображення коду сторінки. Ви там не побачите фрагментів “asp:” і коду на мові C#. Серверні елементи управління (Server controls) були конвертовані в еквівалентні елементи HTML (з невеликим додаванням JavaScript). Це одна з основних властивостей серверних елементів управління – ви звертаєтеся до ним програмно як до звичайних об'єктів .NET Framework через методи, властивості і події. А коли вони будуть передані на Web сервер, вони конвертуються в HTML, надаючи вам можливість використовувати будь-які HTML браузеры для відображення форм ASP.NET під час роботи застосування.

Після закінчення вивчення файлу закрийте Notepad.

Page 133: метуказлабраб ооп 2011укр

133

51. Клацніть кнопку Save.

Елемент InfoLabel відобразить інформацію про нового службовця.

52. Клацніть кнопку Clear.

Відбудеться очищення форми.

Короткі теоретичні відомості.

Застосування ASP.NET

ASP.NET – це спосіб, передбачений .NET для створення динамічних web-сайтів. Як і ADO.NET, ASP.NET запозичує свою назву від попередньої технології Active Server Pages (ASP – активні серверні сторінки), але в даному випадку схожість цим практично і обмежується. Тоді як ASP-сторінки інтерпретувалися і створювалися на функціонально обмежених мовах опису сценаріїв VBScript і JScript, застосування ASP.NET компілюються на мову MSIL точно так, як і інші застосування .NET. Це означає, що у вас з'являється можливість описувати їх на тих же мовах програмування, що і решта застосувань .NET, наприклад на C#.

Іншою величезною перевагою ASP.NET є використання елементів, що управляють, на стороні сервера. У ASP також була можливість елементи HTML (такі як кнопки і інші елементи форм), що управляють, в створювані сторінки, проте робити це доводилося уручну, а реагувати на будь-яке введення користувача в такі елементи можна було або за допомогою виконання сценарію JavaScript на клієнтській стороні, або повторно відправляючи сторінку серверу. У першому випадку проблема полягала в тому, що в різних браузерах використовуються різні реалізації JavaScript, тому практично не представляється можливим створювати такі витончені програми, які могли б працювати як на Netscape, так і на IE.

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

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

Останнє, і, можливо, найбільш важлива поважна перевага полягає в тому, що ASP.NET надає простий спосіб створення web-служб.

Page 134: метуказлабраб ооп 2011укр

134

ЛІТЕРАТУРА

1. Робинсон С., Корнес О. и др. C# для профессионалов. В 2-х томах. – М.: Лори, 2003

2. Ватсон К. и др. C#. М.: Лори, 2004

3. Microsoft Corporation. Разработка Windows-приложений на Visual Basic .NET и Visual C# .NET. Учебный курс MCAD/MCSD. – Пер. с англ. – М.: Русская редакция, 2003

4. Байдачный С.С. .NET Framework. Секреты создания Windows-приложений – М.: СОЛОН-Пресс, 2004

5. Дубовцев А.В. Microsoft .NET в подлиннике. – СПб.: БХВ-Петербург, 2004

6. Либерти Д. Программирование на C# . – М.: Символ-Плюс, 2003

7. Троельсен Э. C# и платформа .NET. Библиотека программиста. – СПб.: Питер, 2005

8. Шилдт Г. C#: учебный курс – СПб.: Питер, 2002

9. Шилдт Г. Полный справочник по C#. – М.: Вильямс, 2004

10. Рихтер Дж. Программирование на платформе Microsoft .NET. – М.: Русская редакция, 2003

11. Микельсен Язык программирования C#. Лекции и упражнения – К.: ДиаСофт, 2002

12. Петцольд Ч. Программирование для Microsoft Windows на C#. В 2-х томах. – М.: Русская редакция, 2002

13. Петцольд Ч. Программирование в тональности C#. – М.: Русская редакция, 2004

14. Использование C#. Специальное издание. – М.: Вильямс, 2002

15. Пономарев В. Программирование на C++/C# Visual Studio.NET 2003. – M.: BHV, 2004

16. Секунов Н. Самоучитель C#. – М.: BHV, 2003

17. Фролов А., Фролов Г. Язык C#. Самоучитель. – М.: Диалог-МИФИ, 2002

18. Арчер Т. Основы C#. Новейшие технологии. – М.: Русская редакция, 2001

19. Майо Дж. C#. Искусство программирования. – К.: ДиаСофт, 2002

20. Тай Т., Лэм Х. К. Платформа .NET. Основы. – Пер. с англ. – СПб: Символ-Плюс, 2003

21. Sharp J. Microsoft Visual C# 2005 Step by Step. – Microsoft Press, 2006

22. Pro C# 2005 and the .NET 2.0 Platform, Third Edition by Andrew Troelsen Publisher: Apress; 3rd edition (September 12, 2005)

23. C# 2.0 : Practical Guide for Programmers (The Practical Guides) by Michel de Champlain, Brian G. Patrick Publisher: Morgan Kaufmann (February 22, 2005)

24. Professional .NET 2.0 Generics (Programmer to Programmer) by Tod Golding Publisher: WROX (October 21, 2005)

25. C# 2005 For Dummies (For Dummies (Computer/Tech)) by Stephen Randy Davis, Charles Sphar Publisher: For Dummies; Bk&CD-Rom edition (October 28, 2005)

26. Core C# and .NET (Core) (Paperback) by Stephen C. Perry Publisher: Prentice Hall PTR (September 6, 2005)

27. Материал из Википедии — свободной энциклопедии. http://ru.wikipedia.org/wiki/C_Sharp

28. C# Course examples from Long Island University – http://phoenix.liu.edu/~mdevi/

29. Програмиране за .NET Framework //Светлин Наков и коллектив. –София: "Фабер", 2005

30. Основы программирования на C#. Интернет-Университет Информационных Технологий http://www.INTUIT.ru