Вивчаємо Visual Studio. NET. Частина 3. Компоненти Windows-додатків

Частина 2



У попередній статті розповідалося, як за допомогою Microsoft Visual Studio. NET створювати Windows-додатки. Ми розглянули основні елементи середовища розробки, які використовуються в цьому процесі, ознайомилися з типами інтерфейсних елементів, а також дізналися, як створити просте одновіконному і MDI-додаток. Крім того, ми розглянули файли, з яких складається проект, та отримали уявлення про їх вміст. У даній статті ми завершуємо знайомство з Microsoft Visual Studio. NET, розповімо про базові принципи організації Windows-додатків і наведемо ряд прикладів використання компонентів, що реалізують інтерфейсні елементи.


Зміст



Генерація коду Windows-додатків


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


Виділимо у вікні Solution Explorer елемент Form1.vb і з контекстного меню цього елемента виберемо пункт View code.


Ми побачимо, що в редакторі коду містяться відомості про те, що клас Form1 є спадкоємцем класу System.Windows.Forms.Form.


Заглянувши в блок "Windows Form Designer generated code", ми знайдемо там наступний ініціалізаційний код:



Public Class Form1
Inherits System.Windows.Forms.Form

#Region “Windows Form Designer generated code”

Public Sub New()
MyBase.New()

“This call is required by the Windows Form Designer.
InitializeComponent()

“Add any initialization after the InitializeComponent() call

End Sub

“Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing _
As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

“Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

“NOTE: The following procedure is required by the Windows Form
“Designer. It can be modified using the Windows Form Designer.
“Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = “Form1”
End Sub

#End Region

End Class


Що означає код, наведений вище? Опис класу форми Form1 починається з конструктора New (), в якому викликаються конструктор базового класу і процедура InitializeComponent – в ній не започатковано компоненти, які розміщуються на формі (на даний момент відсутні). Спочатку процедура InitializeComponent виконує одне-єдине дія – встановлює значення властивості форми Text (напис на її заголовку). Далі листується метод Dispose класу форми, що відповідає за звільнення ресурсів, споживаних формою і утримуються на ній компонентів. Відзначимо, що в цьому методі некеровані ресурси повинні бути обов'язково звільнені, а керовані ресурси повинні стати доступні збирачеві сміття (докладніше про керованих і некерованих ресурсах ви можете прочитати у циклі статей, присвячених Microsoft .NET Framework).


Тепер додамо до форми кнопку (компонент Button) і з'ясуємо, що змінилося при цьому в згенерованому Visual Studio. NET коді.


Ми виявимо, що серед полів класу Form1 тепер є поле Button1 – спадкоємець класу System. Windows.Forms.Button, а у процедурі InitializeComponent тепер з'явився код створення екземпляра цього класу і присвоєння значень його властивостям Location, Size, Name, Text, TabIndex, а також з'явився код, який відповідає за розміщення і відображення кнопки на формі:



Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button()
Me.SuspendLayout()

“Button1

Me.Button1.Location = New System.Drawing.Point(16, 32)
Me.Button1.Name = “Button1”
Me.Button1.Size = New System.Drawing.Size(104, 32)
Me.Button1.TabIndex = 0
Me.Button1.Text = “Button1”

“Form1

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.AddRange (New System.Windows.Forms.Control () {Me.Button1})
Me.Name = “Form1”
Me.Text = “Form1”
Me.ResumeLayout(False)

End Sub


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


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


Тепер спробуємо обробити подія Click кнопки, клацнувши по ній двічі. При цьому буде згенерована заготівля функції – обробника події, до якої слід вписувати код його обробки:



Private Sub Button1_Click (ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles Button1.Click
MessageBox.Show(“Button1 was clicked”)
End Sub


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


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


Інтерфейсні елементи Windows-додатків


Загальні властивості, події і методи


Базовим класом всіх інтерфейсних елементів Windows-додатків в. NET Framework є клас System. Windows.Forms.Control, що міститься в просторі імен System. Windows.Forms. Саме в цьому класі визначено загальні для всіх інтерфейсних елементів властивості, події і методи. Перерахуємо найбільш важливі з них:



З найбільш важливих методів цього класу слід відзначити методи BringToFront, SendToBack, Show, Hide, Contains, Refresh, Update, а з подій – події, пов'язані з переміщенням миші і натисканням на клавіші MouseDown, MouseMove, MouseUp, MouseLeave, MouseHover, MouseEnter, MouseWheel, KeyDown, KeyPress, KeyUp, Click, із застосуванням операції drag-and-drop: DragDrop, DragEnter, DragLeave, DragOver, а також пов'язані зі зміною розміру елемента – Resize – і його перемальовуванням – Paint.


Всі ці властивості, методи і події присутні у всіх елементів управління, оскільки вони є спадкоємцями класу Control, інші ж властивості, події і методи елементів управління призначені для використання в додатках їх специфічної функціональності.


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


Застосування компонентів DataSet, DataGrid і DateTimePicker


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


Для цього створимо новий проект і розмістимо на формі нашого застосування дві кнопки і по одному елементу управління TextBox, DateTimePicker і DataGrid. Змінимо написи на кнопках (властивість Text) на «Додати подія », і« сховати форму ». Встановимо властивість FormBorderStyle форми рівним FixedSingle – це запобіжить зміна користувачем її розмірів.


За допомогою компонента DateTimePicker користувач може ввести дату і час події, про який йому слід нагадати. В елементі управління Text1 він може ввести текст нагадування. Однак список подій, містить ці дані, потрібно десь зберегти, і розумним представляється зберегти його не просто в пам'яті, а у файлі на жорсткому диску – в цьому випадку відомості про майбутні події не будуть втрачені після перезапуску програми. Нехай це буде XML-документ.


Оскільки список подій – це, по суті, набір даних, скористаємося компонентом DataSet з вкладки Data у палітрі компонентів. Так як цей компонент Невізуальний, перетягуючи його на форму він виявиться в нижній частині вікна дизайнера форм. Компонент DataSet представляє інтерфейс до кеша в пам'яті, в якому можуть міститися одна або кілька таблиць (in-memory tables), які можуть бути результатом запиту до бази даних, читання XML-документа, а можуть бути створені на самому додатку «з нічого». У даний момент цей набір даних не містить жодної таблиці, і зараз ми займемося її створенням.


Для створення таблиці зі списком подій виберемо щойно створений компонент DataSet1 і клацнемо мишею біля властивості Tables у вікні Properties.


У результаті отримаємо вікно Tables Collection Editor, в якому ми можемо натиснути клавішу Add і додати до колекції Tables класу DataSet1 нову таблицю, якої привласнимо ім'я Schedule.


Далі слід визначити, що представляють собою поля цієї таблиці. Для цього в редакторі Tables Collection Editor клацнемо мишею біля властивості Columns, після чого на екрані з'явиться вікно Columns Collection Editor редактора колекції полів створеної таблиці. За допомогою кнопки Add додамо в неї три поля – EventID, DateTime і Message і встановимо їх типи даних рівними System.Int32, System.DateTime і System.String. Встановимо значення властивості AutoIncrement поля DateTime рівним True – це дозволить не піклуватися про присвоєння значень цього поля в коді програми.


Натискаємо кнопку Close у редакторі Columns Collection Editor. У редакторі Tables Collection Editor, який як і раніше відкритий, встановимо значення PrimaryKey таблиці Schedule рівним імені першої колонки і закриємо цей редактор. Структура таблиці готова. Встановимо властивість DataSource елемента управління DataGrid1 рівним DataTable1.


Тепер змінимо зовнішній вигляд елемента керування DataGrid – як мінімум, нам потрібно, щоб ширина колонок відповідала відображуваним даними. Для цієї мети нам слід створити колекцію стилів відображення таблиць – DataGridTableStyles. Клацнемо по кнопці біля властивості TableStyles елемента управління DataGrid1 і в що з'явилася діалогової панелі створимо один з елементів такої колекції. Встановимо його властивість MappingName рівним імені відображається таблиці – Schedule; тепер ця таблиця буде мати такий вигляд, який описаний в даному стилі. У цій же діалогової панелі можна вибрати і інші параметри відображення даних (наприклад, колір тексту, фону, обрамлення, ліній і т.д.). У загальному випадку елемент управління DataGrid може бути пов'язаний з компонентом DataSet, що містить кілька таблиць, – тоді можна відображати різні таблиці різними стилями.


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


Створимо три елементи цієї колекції – по одному на кожне поле таблиці – і встановимо їх властивості Width (ширина) і HeaderText (заголовок) відповідно до даних, що містяться в цій таблиці. Встановимо також значення властивості Format другої колонки рівним «f» – в цьому випадку дані типу DateTime відображаються повністю і відповідно до регіональних настройки цього комп'ютера.


У результаті елемент управління DataGrid1 придбає вигляд, зображений на рисунку:


Тепер нам слід подбати про збереження даних у файлі (нехай він називається c: Schedule.xml) і зчитуванні їх з файлу. Видається цілком розумним зчитувати файл при завантаженні форми, тому ми створимо обробник події Load форми:



Private Sub Form1_Load (ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load

Try
DataSet1.ReadXml(“c:Schedule.xml”)
Catch
DataSet1.WriteXml(“c:Schedule.xml”)
MessageBox.Show ("Файл з розписом не знайдений." & _
"Створено новий")
End Try

End Sub


У цьому фрагменті коду ми зчитуємо файл c: Schedule.xml, якщо він існує, і створюємо новий (порожній), якщо він не знайдений.


Має сенс також зберігати файл з даними про події при додаванні до нього нових записів. Тому реалізуємо відповідний код в обробнику події Click кнопки з написом «Додати подію»:



Private Sub Button1_Click (ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button1.Click

Dim DR As DataRow = DataSet1.Tables(0).NewRow()
DR(1) = DateTimePicker1.Value
DR(2) = TextBox1.Text
DataSet1.Tables(0).Rows.Add(DR)
DataSet1.WriteXml(“c:Schedule.xml”)
DataGrid1.Refresh()

End Sub


У цьому фрагменті коду ми створюємо новий об'єкт DataRow і присвоюємо його другому і третьому полю значення, лічені з елементів управління DateTimePicker1 і TextBox1 (значення ж першого поля будуть присвоюватися автоматично, оскільки ми вказали, що воно автоінкрементні). Потім додаємо цей об'єкт DataRow до колекції рядків створеної раніше таблиці, зберігаємо її в XML-файлі і оновлюємо вміст елемента керування DataGrid.


Далі змінимо зовнішній вигляд і поведінку елемента управління DateTimePicker1, дозволивши користувачеві вибирати окремо рік, місяць, день, годину та хвилини. Для цього встановимо властивість ShowUpDown цього елемента управління рівним True і у вже створений обробник події Load форми додамо фрагмент коду (він виділений жирним шрифтом), в якому значення властивості Format цього елемента керування встановлюється рівним Custom, а значення властивості CustomFormat – рівним рядку "MMMM dd, yyyy – dddd, hh: mm", що дасть змогу вводити в цьому елементі рік, місяць, день, годину та хвилини і відображати день тижня. Заодно заборонимо вводити значення часу, пов'язані з минулим:



Private Sub Form1_Load (ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load

DateTimePicker1.MinDate() = Now()
DateTimePicker1.Format = DateTimePickerFormat.Custom
DateTimePicker1.CustomFormat = “MMMM dd, yyyy – dddd, hh:mm”
Try
DataSet1.ReadXml(“c:Schedule.xml”)
Catch
DataSet1.WriteXml(“c:Schedule.xml”)
MessageBox.Show ("Файл з розписом не знайдений. Створений новий")
End Try

End Sub


Ось як приблизно виглядає XML-файл зі списком подій після їх введення за допомогою створеного програми:



<?xml version=”1.0″ standalone=”yes”?>
<ScheduleDataSet>
<Schedule>
<EventID>1</EventID>
<DateTime> 2002-04-21T16: 15:00.0000000 +04:00 </ DateTime>
<Message> Тестове подія 1 </ Message>
</Schedule>
<Schedule>
<EventID>2</EventID>
<DateTime> 2002-04-21T18: 42:24.0000000 +04:00 </ DateTime>
<Message> Тестове подія 2 </ Message>
</Schedule>
<Schedule>
<EventID>3</EventID>
<DateTime> 2002-04-21T18: 47:03.0000000 +04:00 </ DateTime>
<Message> Вимкнути сервер на ніч </ Message>
</Schedule>
<Schedule>
<EventID>4</EventID>
<DateTime> 2002-04-21T18: 49:01.2592912 +04:00 </ DateTime>
<Message> Зателефонувати Іванову з приводу завтрашнього зібрання </ Message>
</Schedule>
<Schedule>
<EventID>5</EventID>
<DateTime> 2002-04-21T19: 02:34.4686288 +04:00 </ DateTime>
<Message> Тестове подія 3 </ Message>
</Schedule>
</ScheduleDataSet>


Отже, ми навчилися вводити опису подій, відображати їх у DataGrid і зберігати в XML-файлі. Наша наступна задача – додати до додатка можливість оповіщати про них користувача. Цим ми займемося в наступному розділі.


Застосування компонентів Timer і NotifyIcon


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


Додамо компонент Timer в наш додаток і встановимо його властивість Interval рівним 60 000, що відповідає одній хвилині, а властивість Enabled рівним True.


Створимо обробник події Tick:



Private Sub Timer1_Tick_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer1.Tick

Dim DR As DataRow
Dim DT As New DateTime()
For Each DR In DataSet1.Tables(0).Rows
DT = CType(DR(1), DateTime)
If (Now() > DT And Now() < DT.AddMinutes(1)) Then
MessageBox.Show(DR(2))
End If
Next

End Sub


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


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


Для цієї мети ми можемо використовувати компонент NotifyIcon, що дозволяє створити таку піктограму. Це Невізуальний компонент, основними властивостями якого є Icon (графічний файл з піктограмою – У нашому прикладі це зображення будильника), Text (напис на ярличку з підказкою) і ContextMenu.


Створимо оброблювачі цих подій:



Private Sub MenuItem4_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MenuItem4.Click
Application.Exit()
End Sub

Private Sub MenuItem1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MenuItem1.Click
Me.Show()
End Sub


Наведений вище фрагмент коду реалізує наступні можливості: при виборі пункту «Список подій» головна форма програми стає видимої, а при виборі пункту «Закрити» додаток закривається. Залишилося тільки змусити форму закриватися при натисканні кнопки «сховати форму»:



Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Me.Hide()
End Sub


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


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


Висновок


У цій статті ми розповіли про базові принципи організації Windows-додатків і привели ряд прикладів використання компонентів, що реалізують інтерфейсні елементи. На цьому ми завершуємо наше знайомство з Visual Studio. NET. Подальший розгляд цього продукту виходить за рамки тематики нашого журналу.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*