5. Графічні інтерфейси з використанням VB.NET та VS.NET
Тут ми пропонуємо показати, як створювати графічні інтерфейси за допомогою VB.NET. Спочатку розглянемо базові класи платформи .NET, які дозволяють нам створювати графічний інтерфейс. На початковому етапі ми не використовуємо жодних інструментів автоматичного генерування. Потім ми скористаємося Visual Studio.NET (VS.NET) — інструментом розробки від Microsoft, що полегшує розробку додатків на мовах .NET, зокрема створення графічних інтерфейсів. Ми використовуємо англійську версію VS.NET.
5.1. Основи графічних інтерфейсів
5.1.1. Просте вікно
Розглянемо такий код:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' клас форми
Public Class Form1
Inherits Form
' виробник
Public Sub New()
' заголовок вікна
Me.Text = "Mon premier formulaire"
' розміри вікна
Me.Size = New System.Drawing.Size(300, 100)
End Sub
' тестова функція
Public Shared Sub Main(ByVal args() As String)
' відображається форма
Application.Run(New Form1)
End Sub
End Class
Попередній код компілюється, а потім виконується
Під час виконання з’являється таке вікно:

Графічний інтерфейс зазвичай походить від базового класу System.Windows.Forms.Form:
Базовий клас Form визначає базове вікно з кнопками закриття, розгортання/згортання, регульованим розміром тощо та обробляє події для цих графічних об’єктів. Тут ми спеціалізуємо базовий клас, задаючи йому заголовок, ширину (300) та висоту (100). Це робиться у його конструкторі:
Public Sub New()
' заголовок вікна
Me.Text = "Mon premier formulaire"
' розміри вікна
Me.Size = New System.Drawing.Size(300, 100)
End Sub
Заголовок вікна задається властивістю Text, а розміри — властивістю Size. Size визначено в просторі імен System.Drawing і є структурою. Процедура Main запускає графічний додаток наступним чином:
Application.Run(New Form1)
Створюється та відображається форма типу Form1, після чого додаток починає відстежувати події, що відбуваються у формі (клацання, переміщення миші тощо), і запускає ті з них, які підтримує форма. У даному випадку наша форма не обробляє жодних інших подій, окрім тих, що обробляються базовим класом Form (натискання кнопок закриття, збільшення/зменшення, зміна розміру вікна, переміщення вікна тощо).
5.1.2. Форма з кнопкою
Тепер додамо кнопку до нашого вікна:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Drawing
Imports System.Windows.Forms
' клас форми
Public Class Form1
Inherits Form
' атрибути
Private cmdTest As Button
' конструктор
Public Sub New()
' заголовок
Me.Text = "Mon premier formulaire"
' розміри
Me.Size = New System.Drawing.Size(300, 100)
' кнопка
' створення
Me.cmdTest = New Button
' положення
cmdTest.Location = New System.Drawing.Point(110, 20)
' розмір
cmdTest.Size = New System.Drawing.Size(80, 30)
' назва
cmdTest.Text = "Test"
' менеджер подій
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' додавання кнопки до форми
Me.Controls.Add(cmdTest)
End Sub
' менеджер подій
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' натиснуто кнопку — повідомляємо про це
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
' тестова функція
Public Shared Sub Main(ByVal args() As String)
' відображення форми
Application.Run(New Form1)
End Sub
End Class
Ми додали до форми кнопку:
' кнопка
' створення
Me.cmdTest = New Button
' позиція
cmdTest.Location = New System.Drawing.Point(110, 20)
' розмір
cmdTest.Size = New System.Drawing.Size(80, 30)
' назва
cmdTest.Text = "Test"
' менеджер подій
AddHandler cmdTest.Click, AddressOf cmdTest_Click
' додавання кнопки до форми
Me.Controls.Add(cmdTest)
Властивість Location встановлює координати (110,20) верхньої лівої точки кнопки за допомогою структури Point. Ширина та висота кнопки встановлюються на (80,30) за допомогою структури Size. Властивість Text кнопки дозволяє задати її напис. Клас кнопки має подію Click, яка визначається наступним чином:
де EventHandler — це «делегована» функція з таким сигнатурою:
Це означає, що обробник події [Click] для кнопки повинен мати сигнатуру делегату [EventHandler]. У цьому випадку при натисканні кнопки cmdTest буде викликано метод cmdTest_Click. Він визначений наступним чином відповідно до попереднього шаблону EventHandler:
' обробник події
Private Sub cmdTest_Click(ByVal sender As Object, ByVal evt As EventArgs)
' було натиснуто кнопку — повідомляємо про це
MessageBox.Show("Clic sur bouton", "Clic sur bouton", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Ми просто виводимо повідомлення:

Клас компілюється та виконується:
dos>vbc /r:system.dll /r:system.drawing.dll /r:system.windows.forms.dll frm2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>frm2
Клас MessageBox призначений для виведення повідомлень у вікні. Тут ми використали конструктор
Overloads Public Shared Function Show(ByVal owner As IWin32Window,ByVal text As String,ByVal caption As String,ByVal buttons As MessageBoxButtons,ByVal icon As MessageBoxIcon) As DialogResult
text | повідомлення, яке потрібно відобразити |
caption | заголовок вікна |
buttons | кнопки, що містяться у вікні |
icon | піктограма у вікні |
Параметр buttons може приймати значення з наступних констант:
константа | кнопки |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
Параметр icon може приймати значення з-поміж таких констант:
![]() | те саме, зупинка | ||
те саме Попередження | ![]() | ||
так само, як Asterisk | ![]() | ||
![]() | те саме, Hand | ||
![]() |
Метод Show є статичним методом, який повертає результат типу System.Windows.Forms.DialogResult, що є переліком:
public enum System.Windows.Forms.DialogResult
{
Abort = 0x00000003,
Cancel = 0x00000002,
Ignore = 0x00000005,
No = 0x00000007,
None = 0x00000000,
OK = 0x00000001,
Retry = 0x00000004,
Yes = 0x00000006,
}
Щоб дізнатися, яку кнопку натиснув користувач для закриття вікна типу MessageBox, слід написати:
dim res as DialogResult=MessageBox.Show(..)
if res=DialogResult.Yes then
' натиснуто кнопку «Так»
...
end if
5.2. Створення графічного інтерфейсу за допомогою Visual Studio.NET
Ми повернемося до деяких прикладів, розглянутих раніше, і створимо їх за допомогою Visual Studio.NET.
5.2.1. Початкове створення проєкту
- Запустіть VS.NET і виберіть опцію Fichier/Nouveau/Projet

- введіть параметри вашого проєкту
![]() |
- виберіть тип проекту, який ви хочете створити, у даному випадку проект VB.NET (1)
- виберіть тип програми, яку ви хочете створити, у даному випадку — програму для Windows (2)
- вкажіть, у якій папці ви хочете розмістити підпапку проекту (3)
- вкажіть назву проєкту (4). Це також буде назвою папки, яка міститиме файли проєкту
- назва цієї папки вказана у полі (5)
- Після цього у папці i4 створюється певна кількість папок і файлів:
підпапки папки «проект1» ![]() |
З цих файлів цікавий лише один — файл form1.cs, який є вихідним файлом, пов’язаним із формою, створеною за допомогою VS.NET. Ми повернемося до цього пізніше.
5.2.2. Вікна інтерфейсу VS.NET
Інтерфейс VS.NET тепер відображає деякі елементи нашого проєкту i4:
У нас є вікно проектування графічного інтерфейсу:
![]() |
Вибираючи елементи управління з панелі інструментів (toolbox 2) та розміщуючи їх на поверхні вікна (1), ми можемо створити графічний інтерфейс. Якщо навести курсор миші на «toolbox», вона розширюється і відображає певну кількість елементів управління:

Наразі ми не використовуємо жодного з них. Також на екрані VS.NET ми бачимо вікно «Explorer Solution» (Оглядач рішень):

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

До цих двох об’єктів можна отримати доступ безпосередньо з вікна «Solution Explorer»:
![]() | ![]() |
Відкриті вікна «накопичуються» у головному вікні проектування:

Тут Form1.vb[Design] позначає вікно дизайну, а Form1.vb — вікно коду. Щоб перейти з одного вікна в інше, достатньо натиснути на одну з вкладок. Ще одне важливе вікно, яке відображається на екрані VS.NET, — це вікно властивостей:

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

Тут наведено основні вікна, що щойно були описані, а також їхні комбінації клавіш.
5.2.3. Виконання проекту
Хоча ми ще не написали жодного коду, у нас вже є проект, готовий до виконання. Виконайте команду F5 або Déboguer/Démarrer, щоб запустити його. З’явиться таке вікно:

Це вікно можна розгорнути, згорнути, змінити розмір та закрити.
5.2.4. Код, згенерований VS.NET
Давайте розглянемо код (Affichage/Code) нашого додатка:
Public Class Form1
Inherits System.Windows.Forms.Form
#Область «Код, згенерований Windows Form Designer»
Public Sub New()
MyBase.New()
'Цей виклик необхідний для Windows Form Designer.
InitializeComponent()
'Додайте будь-яку ініціалізацію після виклику InitializeComponent()
End Sub
'Замінений метод Dispose форми для очищення списку компонентів.
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
'Вимагається конструктором Windows Form
Private components As System.ComponentModel.IContainer
'REMARQUE: наступна процедура є обов’язковою для конструктора Windows Form
'Її можна змінити за допомогою конструктора Windows Form.
'Не змінюйте її за допомогою редактора коду.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.Text = "Form2"
End Sub
#Кінець області
End Class
Графічний інтерфейс походить від базового класу System.Windows.Forms.Form:
Базовий клас Form визначає базове вікно з кнопками закриття, розгортання/згортання, регулювання розміру тощо та обробляє події для цих графічних об’єктів. Конструктор форми використовує метод InitializeComponent, у якому створюються та ініціалізуються елементи управління форми.
Public Sub New()
MyBase.New()
'Цей виклик є обов’язковим для конструктора Windows Form.
InitializeComponent()
'Додайте будь-яку ініціалізацію після виклику InitializeComponent()
End Sub
Будь-які інші операції в конструкторі можна виконати після виклику функції InitializeComponent. Метод InitializeComponent
Private Sub InitializeComponent()
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 53)
Me.Name = "Form1"
Me.Text = "Form1"
End Sub
визначає заголовок вікна «Form1», його ширину (292) та висоту (53). Заголовок вікна визначається властивістю Text, а розміри — властивістю Size. Size визначено в просторі імен System.Drawing і є структурою. Щоб запустити цю програму, нам потрібно визначити головний модуль проєкту. Для цього ми використовуємо опцію [Projets/Propriétés]:

У [Objet de démarrage] ми вказуємо [Form1] — це форма, яку ми щойно створили. Щоб запустити виконання, використовуємо опцію [Déboguer/Démarrer]:

5.2.5. Компіляція у вікні командного рядка
Тепер спробуємо скомпілювати та запустити цю програму у вікні командного рядка:
dos>dir form1.vb
14/03/2004 11:53 514 Form1.vb
dos>vbc /r:system.dll /r:system.windows.forms.dll form1.vb
vbc : error BC30420: 'Sub Main' est introuvable dans 'Form1'.
Компілятор повідомляє, що не може знайти процедуру [Main]. Дійсно, VS.NET її не згенерувала. Однак ми вже зустрічали її в попередніх прикладах. Вона має такий вигляд:
Shared Sub Main()
' запускається програма
Application.Run(New Form1) ' où Form1 est le formulaire
End Sub
Додамо до коду [Form1.vb] попередній код і перекомпілюємо:
dos>vbc /r:system.dll /r:system.windows.forms.dll form2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
Form2.vb(41) : error BC30451: Le nom 'Application' n'est pas déclaré.
Application.Run(New Form2)
~~~~~~~~~~~
Цього разу ім'я [Application] невідоме. Це просто означає, що ми не імпортували його простір імен [System.Windows.Forms]. Додамо таку інструкцію:
а потім перекомпілюємо:
Цього разу все пройшло успішно. Запустимо:

Форма типу Form1 створюється та відображається. Можна уникнути додавання процедури [Main], використовуючи опцію /m компілятора, яка дозволяє вказати клас для виконання у випадку, якщо він успадковує System.Windows.Form:
Опція /m:form2 вказує, що класом, який слід виконати, є клас із назвою [form2].
5.2.6. Обробка подій
Після відображення форми програма починає відстежувати події, що відбуваються у формі (клацання, переміщення миші тощо), і виконує ті з них, які підтримує форма. У даному випадку наша форма не обробляє жодних інших подій, окрім тих, що обробляються базовим класом Form (натискання кнопок закриття, збільшення/зменшення, зміна розміру вікна, переміщення вікна тощо). Згенерована форма використовує атрибут components, який ніде не застосовується. Метод dispose тут також ні до чого. Те саме стосується деяких використовуваних просторів імен (Collections, ComponentModel, Data) та простору імен, визначеного для проєкту projet1. Отже, у цьому прикладі код можна спростити до такого вигляду:
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
' конструктор
Public Sub New()
' створення форми з її компонентами
InitializeComponent()
End Sub
Private Sub InitializeComponent()
' розмір вікна
Me.Size = New System.Drawing.Size(300, 300)
' заголовок вікна
Me.Text = "Form1"
End Sub
Shared Sub Main()
' запускаємо додаток
Application.Run(New Form1)
End Sub
End Class
5.2.7. Висновок
Тепер ми приймемо код, згенерований VS.NET, без змін і обмежимося лише додаванням до нього нашого коду, зокрема для обробки подій, пов'язаних з різними елементами управління форми.
5.3. Вікно з полем введення, кнопкою та написом
5.3.1. Графічне оформлення
У попередньому прикладі ми не розміщували компонентів у вікні. Ми розпочинаємо новий проєкт під назвою interface2. Для цього дотримуємося описаної раніше процедури створення проєкту:

Тепер створимо вікно з кнопкою, написом та полем введення:
![]() |
Поля такі:
№ | ім’я | тип | роль |
1 | lblSaisie | Етикетка | назва |
2 | txtSaisie | TextBox | поле для введення даних |
3 | btnAfficher | Кнопка | для відображення вмісту поля введення у діалоговому вікні txtSaisie |
Щоб створити це вікно, можна вчинити наступним чином: клацніть правою кнопкою миші у вікні поза межами будь-якого компонента та виберіть опцію Properties, щоб отримати доступ до властивостей вікна:

Вікно властивостей з’явиться праворуч:

Слід звернути увагу на деякі з цих властивостей:
для встановлення кольору фону вікна | |
для встановлення кольору малюнків або тексту у вікні | |
для прив’язки меню до вікна | |
щоб надати вікну заголовок | |
для визначення типу вікна | |
для визначення шрифту тексту у вікні | |
для визначення назви вікна |
Тут ми встановлюємо властивості Text та Name:
Поля введення та кнопки — 1 | |
frmSaisiesBoutons |
За допомогою панелі «Інструменти»
- виберіть необхідні компоненти
- перетягніть їх у вікно та задайте їм потрібні розміри
![]() | ![]() |
Після вибору компонента в «інструментальному ящику» натисніть клавішу «Esc», щоб приховати панель інструментів, а потім перетягніть і налаштуйте розміри компонента. Зробіть це для трьох необхідних компонентів : Label, TextBox, Button. Щоб вирівняти та правильно змінити розміри компонентів, скористайтеся меню Format: | ![]() |
Принцип форматування такий:
Опція Align дозволяє вирівнювати компоненти | ![]() |
Опція «Make Same Size» дозволяє зробити так, щоб компоненти мали однакову висоту або однакову ширину: | ![]() |
Параметр «Horizontal Spacing» (Горизонтальний інтервал), наприклад, дозволяє вирівнювати компоненти по горизонталі з однаковими проміжками між ними. Те саме стосується опції «Vertical Spacing» для вертикального вирівнювання. Опція «Center in Form» дозволяє вирівняти по центру компонент по горизонталі або по вертикалі у вікні: | ![]() |
Після того як компоненти правильно розміщені у вікні, зафіксуйте їхні властивості. Для цього клацніть правою кнопкою миші на компоненті та виберіть опцію Properties:
Виберіть компонент, щоб відкрити відкрити вікно властивостей. У ньому змініть такі властивості: name: lblSaisie, text: Введення
Виберіть компонент, щоб відкрити його відкрити вікно властивостей. У ньому змініть наступні властивості: name: txtSaisie, text: залиште порожнім
name: cmdAfficher, text: Показати
text: Введення та кнопки - 1 | ![]() |
Ми можемо запустити (Ctrl+F5) наш проєкт , щоб отримати перше уявлення про вікно у дії: | ![]() |
Закрийте вікно. Нам залишається написати процедуру, пов’язану з натисканням кнопки Afficher.
5.3.2. Обробка подій форми
Давайте розглянемо код, який було згенеровано графічним конструктором:
...
Public Class frmSaisiesBoutons
Inherits System.Windows.Forms.Form
' компоненти
Private components As System.ComponentModel.Container = Nothing
Friend WithEvents btnAfficher As System.Windows.Forms.Button
Friend WithEvents lblsaisie As System.Windows.Forms.Label
Friend WithEvents txtsaisie As System.Windows.Forms.TextBox
' конструктор
Public Sub New()
InitializeComponent()
End Sub
...
' ініціалізація компонентів
Private Sub InitializeComponent()
...
End Sub
End Class
Насамперед слід звернути увагу на особливу декларацію компонентів:
- ключове слово Friend вказує на те, що компонент доступний для всіх класів проекту
- ключове слово WithEvents вказує, що компонент генерує події. Тепер розглянемо, як обробляти ці події
Відкрийте вікно коду форми (Вигляд/код або F7):
![]() |
У вікні, показаному вище, є два випадаючі списки (1) і (2). Список (1) — це список компонентів форми:

Список (2) — це перелік подій, пов’язаних із компонентом, обраним у списку (1):

Одне з подій, пов'язаних із компонентом, відображається жирним шрифтом (у цьому випадку — Click). Це подія за замовчуванням для цього компонента. Доступ до обробника цієї конкретної події можна отримати, двічі клацнувши на компоненті у вікні дизайну. VB.net автоматично генерує каркас обробника події у вікні коду та переміщує курсор на нього. Доступ до обробників інших подій здійснюється у вікні коду шляхом вибору компонента у списку (1) та події у (2). VB.net генерує шаблон обробника події або встановлює курсор на ньому, якщо він уже був згенерований:
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
За замовчуванням VB.net C_E присвоює ім’я обробнику події E компонента C. Це ім’я можна змінити, якщо це доцільно. Однак це не рекомендується. Розробники VB зазвичай зберігають ім’я, згенероване VB, що забезпечує узгодженість іменування у всіх програмах VB. Прив’язування процедури btnAfficher_Click до події Click компонента btnAfficher здійснюється не за назвою процедури, а за допомогою ключового слова handles:
Handles btnAfficher.Click
У наведеному вище прикладі ключове слово handles вказує, що процедура обробляє подію Click компонента btnAfficher. Попередній обробник подій має два параметри:
об’єкт, що є джерелом події (у цьому випадку — кнопка) | |
об’єкт EventArgs, що містить детальну інформацію про подію, яка відбулася |
Ми не будемо використовувати жоден із цих параметрів у цьому випадку. Залишається лише доповнити код. Тут ми хочемо відобразити діалогове вікно з вмістом поля txtSaisie:
Private Sub btnAfficher_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' відображення тексту, введеного у поле введення TxtSaisie
MessageBox.Show("texte saisi= " + txtsaisie.Text, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Якщо запустити додаток, отримаємо таке:

5.3.3. Інший спосіб обробки подій
Для кнопки btnAfficher VS.NET згенерував такий код:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
...
End Sub
...
' обробник події натискання кнопки cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAfficher.Click
...
End Sub
Ми можемо прив’язати процедуру btnAfficher_Click до події Click кнопки btnAfficher іншим способом:
Private Sub InitializeComponent()
...
'
'btnAfficher
'
Me.btnAfficher.Location = New System.Drawing.Point(102, 48)
Me.btnAfficher.Name = "btnAfficher"
Me.btnAfficher.Size = New System.Drawing.Size(88, 24)
Me.btnAfficher.TabIndex = 2
Me.btnAfficher.Text = "Afficher"
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
...
End Sub
...
' обробник події кліка на кнопку cmdAfficher
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
...
End Sub
Процедура btnAfficher_Click втратила ключове слово Handles, тим самим втративши прив’язку до події btnAfficher.Click. Тепер ця прив’язка здійснюється за допомогою ключового слова AddHandler:
AddHandler btnAfficher.Click, AddressOf btnAfficher_Click
Наведений вище код, який буде розміщено в процедурі InitializeComponent форми, пов’язує з подією btnAfficher.Click процедуру з назвою btnAfficher_Click. Крім того, компоненту btnAfficher більше не потрібне ключове слово WithEvents:
Friend btnAfficher As System.Windows.Forms.Button
У чому полягає різниця між цими двома методами?
- Ключове слово handles дозволяє пов’язати подію з процедурою лише на етапі проектування. Проектувальник заздалегідь знає, що процедура P має обробляти події E1, E2, ... і пише код
Private Sub btnAfficher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) handles E1, E2, ..., En
Дійсно, процедура може обробляти кілька подій.
- Ключове слово addhandler дозволяє пов’язати подію з процедурою під час виконання. Це корисно в контексті моделі «виробник-споживач» подій. Об’єкт генерує певну подію, яка може зацікавити інші об’єкти. Останні підписуються на виробника, щоб отримувати цю подію (наприклад, коли температура перевищила критичний поріг). Під час виконання програми виробник події буде виконувати різні інструкції:
де E — подія, що генерується виробником, а Pi — процедури, що належать різним об’єктам-споживачам цієї події. Ми ще повернемося до програми «виробник-споживач» подій у наступному розділі.
5.3.4. Висновок
На основі двох розглянутих проектів можна зробити висновок, що після створення графічного інтерфейсу за допомогою VS.NET робота розробника полягає у написанні обробників подій, які він хоче обробляти для цього графічного інтерфейсу. Надалі ми будемо наводити лише код цих обробників.
5.4. Деякі корисні компоненти
Тепер ми розглянемо різні додатки, що використовують найпоширеніші компоненти, щоб ознайомитися з їхніми основними методами та властивостями. Для кожного додатка ми покажемо графічний інтерфейс та відповідний код, зокрема обробники подій.
5.4.1. Форма Form
Почнемо з огляду найнеобхіднішого компонента — форми, на яку розміщуються інші компоненти. Ми вже розглядали деякі з її основних властивостей. Тут ми зупинимося на кількох важливих подіях форми.
форма завантажується | |
форма закривається | |
форма закрита |
Подія Load відбувається ще до того, як форма з’явиться на екрані. Подія Closing відбувається під час закриття форми. Це закриття ще можна зупинити програмним шляхом. Створюємо форму з іменем Form1 без жодних компонентів:

Ми обробляємо три попередні події:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' початкове завантаження форми
MessageBox.Show("Evt Load", "Load")
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
' форма закривається
MessageBox.Show("Evt Closing", "Closing")
' запитується підтвердження
Dim réponse As DialogResult = MessageBox.Show("Voulez-vous vraiment quitter l'application", "Closing", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If réponse = DialogResult.No Then
e.Cancel = True
End If
End Sub
Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
' форма закривається
MessageBox.Show("Evt Closed", "Closed")
End Sub
Ми використовуємо функцію MessageBox, щоб отримувати сповіщення про різні події. Подія Closing відбудеться, коли користувач закриє вікно. | ![]() |
Тоді ми запитуємо його, чи дійсно він хоче вийти з програми: | ![]() |
Якщо він відповідає «Ні», ми встановлюємо властивість Cancel події CancelEventArgs, яке метод отримав як параметр. Якщо ми встановимо для цього властивості значення False, закриття вікна скасовується, інакше воно продовжується: | ![]() |
5.4.2. етикетки Label та поля введення TextBox
Ми вже зустрічали ці два компоненти. Label — це текстовий компонент, а TextBox — компонент поля введення. Їхньою основною властивістю є Text, яка позначає або вміст поля введення, або текст мітки. Ця властивість доступна для читання та запису. Подія, яка зазвичай використовується для TextBox, — це TextChanged, яка сигналізує, що користувач змінив поле введення. Ось приклад, у якому використовується подія TextChanged для відстеження змін у полі введення:
![]() |
№ | тип | назва | роль |
1 | TextBox | txtSaisie | поле введення |
2 | Етикетка | lblControle | відображає текст з 1 у режимі реального часу |
3 | Кнопка | cmdEffacer | для очищення полів 1 і 2 |
4 | Кнопка | cmdQuitter | для виходу з програми |
Відповідний код цього додатка — це код обробників подій:
' натискання кнопки «Вийти»
Private Sub cmdQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdQuitter.Click
' натискання кнопки «Вийти» — вихід із програми
Application.Exit()
End Sub
' зміна поля txtSaisie
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' вміст поля TextBox змінився — його копіюють у мітку lblControle
lblControle.Text = txtSaisie.Text
End Sub
' натиснуто кнопку «Очистити»
Private Sub cmdEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmdEffacer.Click
' вміст поля введення очищено
txtSaisie.Text = ""
End Sub
' була натиснута клавіша
Private Sub txtSaisie_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles txtSaisie.KeyPress
' перевіряється, яка клавіша була натиснута
Dim touche As Char = e.KeyChar
If touche = ControlChars.Cr Then
MessageBox.Show(txtSaisie.Text, "Contrôle", MessageBoxButtons.OK, MessageBoxIcon.Information)
e.Handled = True
End If
End Sub
Зверніть увагу на спосіб завершення роботи програми у процедурі cmdQuitter_Click: Application.Exit(). У наступному прикладі використовується багаторядковий TextBox:
![]() |
Список елементів управління такий:
№ | тип | назва | роль |
1 | TextBox | txtMultiLignes | багаторядкове поле введення |
2 | TextBox | txtAjout | однорядкове поле введення |
3 | Кнопка | btnAjouter | Додає вміст з 2 до 1 |
Щоб TextBox став багаторядковим, слід встановити такі властивості елемента управління:
для підтримки декількох рядків тексту | |
щоб встановити, чи має елемент управління смуги прокрутки (Horizontal, Vertical, Both) чи ні (None) | |
якщо значення дорівнює true, клавіша Enter буде переносити курсор на новий рядок | |
якщо значення true, клавіша Tab створюватиме табуляцію в тексті |
Корисний код — це той, що обробляє натискання кнопки [Ajouter], та той, що обробляє зміну значення поля введення [txtAjout]:
' можливо btnAjouter_Click
Private Sub btnAjouter_Click1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' додавання вмісту txtAjout до вмісту txtMultilignes
txtMultilignes.Text &= txtAjout.Text
txtAjout.Text = ""
End Sub
' або txtAjout_TextChanged
Private Sub txtAjout_TextChanged1(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtAjout.TextChanged
' встановлюємо стан кнопки «Додати»
btnAjouter.Enabled = txtAjout.Text.Trim() <> ""
End Sub
5.4.3. випадаючі списки ComboBox
![]() | ![]() |
Компонент ComboBox — це випадаючий список, доповнений полем введення: користувач може або вибрати елемент у (2), або ввести текст у (1). Існує три типи ComboBox, що визначаються властивістю Style:
нерозгортальний список із полем редагування | |
розгортальний список із полем редагування | |
розгортальний список без поля редагування |
За замовчуванням тип ComboBox — це DropDown. Щоб дізнатися про клас ComboBox, введіть ComboBox в індексі довідки (Aide/Index). Клас ComboBox має лише один конструктор:
Public Sub New() | створює порожній об’єкт ComboBox |
Елементи ComboBox доступні у властивості Items:
Це індексоване властивість, де Items(i) позначає елемент i комбо-поля. Нехай C — це комбо-поле, а C.Items — його список елементів. Маємо такі властивості:
кількість елементів комбо-поля | |
елемент i комбінованого списку | |
додає об’єкт o як останній елемент комбінації | |
додає масив об’єктів у кінець комбінації | |
додає об’єкт o на позицію i комбо | |
видаляє елемент i з комбо | |
видаляє об’єкт o зі списку | |
видаляє всі елементи з комбінації | |
повертає позицію i об'єкта o у комбінованому списку |
Може здатися дивним, що комбо-поле може містити об’єкти, хоча зазвичай воно містить символьні рядки. Візуально це саме так і виглядає. Якщо ComboBox містить об’єкт obj, воно відображає рядок obj.ToString(). Нагадаємо, що кожен об’єкт має метод ToString, успадкований від класу object, який повертає символьний рядок, що «представляє» цей об’єкт. Елемент, вибраний у комбінованому списку C, — це C.SelectedItem або C.Items(C.SelectedIndex), де C.SelectedIndex — це номер вибраного елемента, який починається з нуля для першого елемента.
Під час вибору елемента у випадаючому списку відбувається подія SelectedIndexChanged, яку можна використовувати для отримання сповіщення про зміну вибору у комбінованому списку. У наведеному нижче прикладі ми використовуємо цю подію для відображення елемента, який було вибрано зі списку.

Ми наводимо лише відповідний код вікна. У конструкторі форми ми заповнюємо комбінований список:
Public Sub New()
' створення форми
InitializeComponent()
' заповнення комбінованого списку
cmbNombres.Items.AddRange(New String() {"zéro", "un", "deux", "trois", "quatre"})
' вибираємо перший елемент зі списку
cmbNombres.SelectedIndex = 0
End Sub
Ми обробляємо подію SelectedIndexChanged комбінованого списку, яка сигналізує про новий вибраний елемент:
Private Sub cmbNombres_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cmbNombres.SelectedIndexChanged
' вибраний елемент змінився — відображаємо його
MessageBox.Show("Elément sélectionné : (" & cmbNombres.SelectedItem.ToString & "," & cmbNombres.SelectedIndex & ")", "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
5.4.4. компонент ListBox
Ми пропонуємо створити такий інтерфейс:
![]() |
Компоненти цього вікна такі:
№ | тип | назва | роль/властивості |
0 | Форма | Form1 | форма - BorderStyle=FixedSingle |
1 | TextBox | txtSaisie | поле для введення даних |
2 | Кнопка | btnAjouter | кнопка, що дозволяє додати вміст поля введення 1 до списку 3 |
3 | ListBox | listBox1 | список 1 |
4 | ListBox | listBox2 | список 2 |
5 | Кнопка | btn1TO2 | переносить вибрані елементи зі списку 1 до списку 2 |
6 | Кнопка | cmd2T0 | виконує зворотну дію |
7 | Кнопка | btnEffacer1 | очистити список 1 |
8 | Кнопка | btnEffacer2 | очистити список 2 |
- Користувач вводить текст у поле 1. Він додає його до списку 1 за допомогою кнопки Ajouter (2). Поле введення (1) при цьому очищується, і користувач може додати новий елемент.
- Він може переносити елементи з одного списку в інший, вибравши елемент для перенесення в одному зі списків та натиснувши відповідну кнопку перенесення 5 або 6. Перенесений елемент додається в кінець списку призначення та видаляється зі списку-джерела.
- Користувач може двічі клацнути на елементі зі списку 1. Цей елемент переноситься у поле введення для редагування та видаляється зі списку 1.
Кнопки вмикаються або вимикаються за такими правилами:
- кнопка Ajouter підсвічується лише тоді, коли в полі введення є текст, що не є порожнім
- кнопка 5 для перенесення зі списку 1 до списку 2 підсвічується лише тоді, коли у списку 1 вибрано елемент
- кнопка 6 для перенесення зі списку 2 до списку 1 підсвічується лише тоді, коли у списку 2 вибрано елемент
- кнопки 7 і 8 для очищення списків 1 і 2 підсвічуються лише тоді, коли список, який потрібно очистити, містить елементи.
За зазначених умов усі кнопки мають бути вимкнені під час запуску програми. Тому властивість Enabled кнопок слід встановити на значення false. Це можна зробити на етапі проектування, що призведе до генерації відповідного коду в методі InitializeComponent, або зробити це самостійно у конструкторі, як показано нижче:
Public Sub New()
' початкове створення форми
InitializeComponent()
' додаткові ініціалізації
' деякі кнопки вимкнено
btnAjouter.Enabled = False
btn1TO2.Enabled = False
btn2TO1.Enabled = False
btnEffacer1.Enabled = False
btnEffacer2.Enabled = False
End Sub
Стан кнопки Ajouter контролюється вмістом поля введення. Подія TextChanged дозволяє відстежувати зміни цього вмісту:
' зміна у полі введення тексту
Private Sub txtSaisie_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSaisie.TextChanged
' змінився вміст txtSaisie
' кнопка «Додати» активна лише тоді, коли поле введення не порожнє
btnAjouter.Enabled = txtSaisie.Text.Trim() <> ""
End Sub
Стан кнопок перенесення залежить від того, чи було вибрано елемент у списку, який вони контролюють:
' зміна вибраного елемента без використання listbox1
Private Sub listBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox1.SelectedIndexChanged
' елемент було вибрано
' вмикається кнопка перенесення з 1 до 2
btn1TO2.Enabled = True
End Sub
' зміна вибраного елемента без використання списку 2
Private Sub listBox2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles listBox2.SelectedIndexChanged
' елемент було вибрано
' вмикається кнопка перенесення з 2 до 1
btn2TO1.Enabled = True
End Sub
Код, пов’язаний із натисканням кнопки Ajouter, є таким:
' натискання кнопки «Додати»
Private Sub btnAjouter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnAjouter.Click
' додано новий елемент до списку 1
listBox1.Items.Add(txtSaisie.Text.Trim())
' очищення поля введення
txtSaisie.Text = ""
' Список 1 не порожній
btnEffacer1.Enabled = True
' повернення фокусу на поле введення
txtSaisie.Focus()
End Sub
Зверніть увагу на метод Focus, який дозволяє встановити «фокус» на елементі управління форми. Код, пов'язаний з натисканням на кнопки Effacer:
' натискання кнопки «Очистити1»
Private Sub btnEffacer1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer1.Click
' Список 1 очищено
listBox1.Items.Clear()
btnEffacer1.Enabled = False
End Sub
' натискання кнопки «Очистити2»
Private Sub btnEffacer2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
' список 2 очищено
listBox2.Items.Clear()
btnEffacer2.Enabled = False
End Sub
Код для перенесення вибраних елементів з одного списку в інший:
' натискання кнопки «btn1to2»
Private Sub btn1TO2_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn1TO2.Click
' перенесення вибраного елемента зі списку 1 до списку 2
transfert(listBox1, listBox2)
' кнопки «Очистити»
btnEffacer2.Enabled = True
btnEffacer1.Enabled = listBox1.Items.Count <> 0
' кнопки переміщення
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' натискання кнопки btn2to1
Private Sub btn2TO1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btn2TO1.Click
' перенесення вибраного елемента зі Списку 2 до Списку 1
transfert(listBox2, listBox1)
' кнопки «Видалити»
btnEffacer1.Enabled = True
btnEffacer2.Enabled = listBox2.Items.Count <> 0
' кнопки перенесення
btn1TO2.Enabled = False
btn2TO1.Enabled = False
End Sub
' перенесення
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
' перенесення вибраного елемента зі списку 1 до списку l2
' вибраний елемент?
If l1.SelectedIndex = -1 Then Return
' додати до l2
l2.Items.Add(l1.SelectedItem)
' видалення зі списку l1
l1.Items.RemoveAt(l1.SelectedIndex)
End Sub
Спочатку створюємо метод
Private Sub transfert(ByVal l1 As ListBox, ByVal l2 As ListBox)
, який переносить у список l2 елемент, вибраний зі списку l1. Це дозволяє нам використовувати лише один метод замість двох для перенесення елемента зі списку listBox1 до списку listBox2 або зі списку listBox2 до списку listBox1. Перед перенесенням переконуємося, що у списку l1 дійсно вибрано елемент:
' вибраний елемент?
If l1.SelectedIndex = -1 Then Return
Властивість SelectedIndex дорівнює -1, якщо наразі жоден елемент не виділено. У процедурах
Private Sub btnXTOY_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnXTOY.Click
здійснюється перенесення списку X до списку Y та змінюється стан деяких кнопок, щоб відобразити новий стан списків.
5.4.5. прапорці CheckBox, перемикачі ButtonRadio
Ми пропонуємо написати таку програму:
![]() |
Компоненти вікна такі:
№ | тип | іменник | роль |
1 | RadioButton | radioButton1 radioButton2 radioButton3 | 3 перемикачі |
2 | CheckBox | chechBox1 chechBox2 chechBox3 | 3 прапорці |
3 | ListBox | lstValeurs | список |
Якщо створити три перемикачі один за одним, вони за замовчуванням стають частиною однієї групи. Тому, коли один з них позначений, інші не позначені. Подія, яка нас цікавить для цих шести елементів управління, — це подія CheckChanged, що вказує на зміну стану прапорця або перемикача. Цей стан у обох випадках представлений булевою властивістю Check, яка при значенні «true» означає, що елемент управління відмічений. Тут ми використали єдиний метод для обробки шести подій CheckChanged — метод affiche:
' відображає
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles checkBox1.CheckedChanged, checkBox2.CheckedChanged, checkBox3.CheckedChanged, _
radioButton1.CheckedChanged, radioButton2.CheckedChanged, radioButton3.CheckedChanged
' відображає стан перемикача або прапорця
' чи це прапорець?
If (TypeOf (sender) Is CheckBox) Then
Dim chk As CheckBox = CType(sender, CheckBox)
lstValeurs.Items.Insert(0, chk.Name & "=" & chk.Checked)
End If
' чи це перемикач?
If (TypeOf (sender) Is RadioButton) Then
Dim rdb As RadioButton = CType(sender, RadioButton)
lstValeurs.Items.Insert(0, rdb.Name & "=" & rdb.Checked)
End If
End Sub
Синтаксис TypeOf (відправник) Is CheckBox дозволяє перевірити, чи об’єкт sender має тип CheckBox. Це дозволяє нам потім виконати перетворення типу до точного типу sender. Метод affiche записує у список lstValeurs назву компонента, що ініціював подію, та значення його властивості Checked. Під час виконання видно, що натискання на перемикач викликає дві події CheckChanged: одну на старому перемикачі, який переходить у стан «не відмічений», та іншу на новому перемикачі, який переходить у стан «відмічений».
5.4.6. регулятори ScrollBar
Існує кілька типів регуляторів: горизонтальний регулятор (hScrollBar), вертикальний регулятор (vScrollBar), інкрементатор (NumericUpDown). | ![]() |
Реалізуємо таку програму:
![]() |
№ | тип | назва | роль |
1 | hScrollBar | hScrollBar1 | горизонтальний регулятор |
2 | hScrollBar | hScrollBar2 | горизонтальний регулятор, що слідує за змінами регулятора 1 |
3 | TextBox | txtValeur | відображає значення горизонтального регулятора ReadOnly=true, щоб запобігти будь-якому введенню даних |
4 | NumericUpDown | інкрементатор | дозволяє зафіксувати значення регулятора 2 |
- Регулятор ScrollBar дозволяє користувачеві вибрати значення в діапазоні цілих чисел, що символізується «смугою» регулятора, по якій переміщується курсор. Значення регулятора доступне у його властивості Value.
- Для горизонтального регулятора лівий край відповідає мінімальному значенню діапазону, правий край — максимальному, а курсор — поточно вибраному значенню. Для вертикального регулятора мінімум відповідає верхньому краю, а максимум — нижніму. Ці значення представлені властивостями Minimum та Maximum і за замовчуванням дорівнюють 0 та 100.
- Клік на крайніх точках повзунка змінює значення на один крок (позитивний або негативний) відповідно до крайньої точки, на яку натиснуто, що називається SmallChange і за замовчуванням дорівнює 1.
- Клік по обидва боки від повзунка змінює значення на один крок (позитивний або негативний) залежно від того, на який кінець було натиснуто, що позначається як LargeChange і за замовчуванням дорівнює 10.
- При натисканні на верхній край вертикального повзунка його значення зменшується. Це може здивувати пересічного користувача, який зазвичай очікує, що значення «зросте». Цю проблему можна вирішити, присвоївши від’ємні значення властивостям SmallChange та LargeChange
- Ці п’ять властивостей (Value, Minimum, Maximum, SmallChange, LargeChange) доступні для читання та запису.
- Головною подією приводу є та, що сигналізує про зміну значення: подія Scroll.
Поруч із регулятором розташований компонент NumericUpDown: він також має властивості Minimum, Maximum та Value, значення яких за замовчуванням становлять 0, 100, 0. Однак у цьому випадку властивість Value відображається у полі введення, яке є невід’ємною частиною елемента управління. Користувач може самостійно змінювати це значення, якщо властивість ReadOnly елемента управління не встановлено у значення «true». Значення кроку встановлюється властивістю Increment, за замовчуванням 1. Головною подією компонента NumericUpDown є та, що сигналізує про зміну значення: подія ValueChanged. Код нашого додатка виглядає наступним чином:
Форма оформлюється під час її створення:
' конструктор
Public Sub New()
' початкове створення форми
InitializeComponent()
' присвоюємо приводу 2 ті самі характеристики, що й приводу 1
hScrollBar2.Minimum = hScrollBar1.Value
hScrollBar2.Minimum = hScrollBar1.Minimum
hScrollBar2.Maximum = hScrollBar1.Maximum
hScrollBar2.LargeChange = hScrollBar1.LargeChange
hScrollBar2.SmallChange = hScrollBar1.SmallChange
' те саме для інкрементатора
incrémenteur.Minimum = hScrollBar1.Value
incrémenteur.Minimum = hScrollBar1.Minimum
incrémenteur.Maximum = hScrollBar1.Maximum
incrémenteur.Increment = hScrollBar1.SmallChange
' присвоюється TextBox значення приводу 1
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Обробник, який відстежує зміни значень приводу 1:
' управління приводом hscrollbar1
Private Sub hScrollBar1_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar1.Scroll
' зміна значення регулятора 1
' його значення передається на регулятор 2 та у текстове поле TxtValeur
hScrollBar2.Value = hScrollBar1.Value
txtValeur.Text = "" & hScrollBar1.Value
End Sub
Модуль, що відстежує зміни значень частотного перетворювача 2:
' управління регулятором hscrollbar2
Private Sub hScrollBar2_Scroll(ByVal sender As Object, ByVal e As System.Windows.Forms.ScrollEventArgs) _
Handles hScrollBar2.Scroll
' блокується будь-яка зміна регулятора 2
' примушуючи його зберігати значення регулятора 1
e.NewValue = hScrollBar1.Value
End Sub
Менеджер, який відстежує зміни параметрів системи управління incrémenteur:
' управління інкрементатором
Private Sub incrémenteur_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles incrémenteur.ValueChanged
' фіксація значення регулятора 2
hScrollBar2.Value = CType(incrémenteur.Value, Integer)
End Sub
5.5. Події миші
Під час малювання в контейнері важливо знати положення миші, щоб, наприклад, відобразити точку під час кліка. Переміщення миші викликають події в контейнері, в якому вона переміщується.
![]() | ![]() |
миша щойно увійшла в область елемента управління | |
миша щойно вийшла з області керування | |
миша рухається в області контролю | |
Натискання лівої кнопки миші | |
Відпускання лівої кнопки миші | |
користувач відпускає об’єкт на елементі управління | |
користувач входить у область елемента управління, перетягуючи об’єкт | |
користувач виходить з області елемента управління, перетягуючи об’єкт | |
користувач наводить курсор на область елемента управління, перетягуючи об’єкт |
Ось програма, яка допоможе краще зрозуміти, в які моменти відбуваються різні події миші:
![]() |
№ | тип | назва | роль |
1 | Етикетка | lblPosition | для відображення положення миші у формі 1, списку 2 або кнопці 3 |
2 | ListBox | lstEvts | для відображення подій миші, відмінних від MouseMove |
3 | Кнопка | btnEffacer | для очищення вмісту 2 |
Існують такі обробники подій. Щоб відстежувати переміщення миші по трьох елементах управління, потрібно написати лише один обробник:
' можливо form1_mousemove
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseMove, lstEvts.MouseMove, btnEffacer.MouseMove, lstEvts.MouseMove
' рух миші — відображення її координат (X, Y)
lblPosition.Text = "(" & e.X & "," & e.Y & ")"
End Sub
Слід знати, що кожного разу, коли миша потрапляє в область елемента управління, її система координат змінюється. Її початок координат (0,0) — це лівий верхній кут елемента управління, на якому вона знаходиться. Таким чином, під час виконання, коли ми пересуваємо мишу з форми на кнопку, ми чітко бачимо зміну координат. Щоб краще побачити ці зміни області миші, можна скористатися властивістю Cursor елементів управління:

Цей атрибут дозволяє задати форму курсора миші, коли вона потрапляє в область елемента управління. Так, у нашому прикладі ми встановили для самої форми значення Default, для списку 2 — Hand, а для кнопки 3 — No, як показано на скріншотах нижче.



У методі [InitializeComponent] код, згенерований на основі цих налаштувань, виглядає так:
Me.lstEvts.Cursor = System.Windows.Forms.Cursors.Hand
Me.btnEffacer.Cursor = System.Windows.Forms.Cursors.No
Крім того, щоб виявити введення та виведення миші у списку 2, ми обробляємо події MouseEnter та MouseLeave з цього самого списку:
' подія lstEvts_MouseEnter
Private Sub lstEvts_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseEnter
affiche("MouseEnter sur liste")
End Sub
' подія lstEvts_MouseLeave
Private Sub lstEvts_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstEvts.MouseLeave
affiche("MouseLeave sur liste")
End Sub
' відображає
Private Sub affiche(ByVal message As String)
' повідомлення відображається у верхній частині списку подій
lstEvts.Items.Insert(0, message)
End Sub

Для обробки кліків у формі ми обробляємо події MouseDown та MouseUp:
' подія Form1_MouseDown
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseDown
affiche("MouseDown sur formulaire")
End Sub
' подія Form1_MouseUp
Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseUp
affiche("MouseUp sur formulaire")
End Sub

І нарешті, код обробника кліка на кнопці Effacer:
' подія btnEffacer_Click
Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' очищає список подій
lstEvts.Items.Clear()
End Sub
5.6. Створення вікна з меню
Тепер розглянемо, як створити вікно з меню. Ми створимо таке вікно:
![]() |
Елемент управління 1 — це TextBox, доступний лише для читання (ReadOnly=true), з іменем txtStatut. Структура меню така:
![]() | ![]() |
Пункти меню є елементами управління, як і інші візуальні компоненти, і мають властивості та події. Наприклад, таблиця властивостей пункту меню A1:

У нашому прикладі використовуються дві властивості:
ім’я елемента управління меню | |
назва пункту меню |
Властивості різних пунктів меню в нашому прикладі такі:
Name | Текст |
mnuA | опції A |
mnuA1 | A1 |
mnuA2 | A2 |
mnuA3 | A3 |
mnuB | варіанти B |
mnuB1 | B1 |
mnuSep1 | - (роздільник) |
mnuB2 | B2 |
mnuB3 | B3 |
mnuB31 | B31 |
mnuB32 | B32 |
Щоб створити меню, виберіть компонент «MainMenu» у панелі «ToolBox»:

У результаті з’являється порожнє меню, яке розміщується у формі з порожніми полями під назвою «Type Here». Достатньо вказати в них різні опції меню:

Щоб вставити роздільник між двома пунктами, як показано вище між пунктами B1 та B2, наведіть курсор на місце, де має бути роздільник у меню, клацніть правою кнопкою миші та виберіть опцію «Insert Separator»:

Якщо запустити додаток за допомогою комбінації клавіш Ctrl+F5, з’явиться форма з меню, яке поки що не виконує жодних дій. Пункти меню обробляються як компоненти: вони мають властивості та події. У [fenêtre de code] виберіть компонент mnuA1, а потім виберіть пов’язані події:

Якщо вище ми генеруємо подію Click, то VS.NET автоматично генерує таку процедуру:
Private Sub mnuA1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuA.Click
....
End Sub
Ми могли б вчинити так для всіх пунктів меню. У цьому випадку для всіх пунктів можна використовувати одну й ту саму процедуру. Тому перейменовуємо попередню процедуру на affiche і оголошуємо події, які вона обробляє:
Private Sub affiche(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mnuA1.Click, mnuA2.Click, mnuB1.Click, mnuB2.Click, mnuB31.Click, mnuB32.Click
' відображає у TextBox назву обраного підменю
txtStatut.Text = (CType(sender, MenuItem)).Text
End Sub
У цьому методі ми обмежуємося відображенням властивості Text пункту меню у джерелі події. Джерело події sender має тип object. Опції меню мають тип MenuItem, тому тут доводиться виконувати перетворення типу з object у MenuItem. Запустіть програму та виберіть опцію A1, щоб отримати таке повідомлення:

Корисний код цієї програми, окрім коду методу affiche, — це код побудови меню у конструкторі форми (InitializeComponent):
Private Sub InitializeComponent()
Me.mainMenu1 = New System.Windows.Forms.MainMenu
Me.mnuA = New System.Windows.Forms.MenuItem
Me.mnuA1 = New System.Windows.Forms.MenuItem
Me.mnuA2 = New System.Windows.Forms.MenuItem
Me.mnuA3 = New System.Windows.Forms.MenuItem
Me.mnuB = New System.Windows.Forms.MenuItem
Me.mnuB1 = New System.Windows.Forms.MenuItem
Me.mnuB2 = New System.Windows.Forms.MenuItem
Me.mnuB3 = New System.Windows.Forms.MenuItem
Me.mnuB31 = New System.Windows.Forms.MenuItem
Me.mnuB32 = New System.Windows.Forms.MenuItem
Me.txtStatut = New System.Windows.Forms.TextBox
Me.mnuSep1 = New System.Windows.Forms.MenuItem
Me.SuspendLayout()
'
' mainMenu1
'
Me.mainMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA, Me.mnuB})
'
' mnuA
'
Me.mnuA.Index = 0
Me.mnuA.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuA1, Me.mnuA2, Me.mnuA3})
Me.mnuA.Text = "Options A"
'
' mnuA1
'
Me.mnuA1.Index = 0
Me.mnuA1.Text = "A1"
'
' mnuA2
'
Me.mnuA2.Index = 1
Me.mnuA2.Text = "A2"
'
' mnuA3
'
Me.mnuA3.Index = 2
Me.mnuA3.Text = "A3"
'
' mnuB
'
Me.mnuB.Index = 1
Me.mnuB.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB1, Me.mnuSep1, Me.mnuB2, Me.mnuB3})
Me.mnuB.Text = "Options B"
'
' mnuB1
'
Me.mnuB1.Index = 0
Me.mnuB1.Text = "B1"
'
' mnuB2
'
Me.mnuB2.Index = 2
Me.mnuB2.Text = "B2"
'
' mnuB3
'
Me.mnuB3.Index = 3
Me.mnuB3.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuB31, Me.mnuB32})
Me.mnuB3.Text = "B3"
'
' mnuB31
'
Me.mnuB31.Index = 0
Me.mnuB31.Text = "B31"
'
' mnuB32
'
Me.mnuB32.Index = 1
Me.mnuB32.Text = "B32"
'
' txtStatut
'
Me.txtStatut.Location = New System.Drawing.Point(8, 8)
Me.txtStatut.Name = "txtStatut"
Me.txtStatut.ReadOnly = True
Me.txtStatut.Size = New System.Drawing.Size(112, 20)
Me.txtStatut.TabIndex = 0
Me.txtStatut.Text = ""
'
' mnuSep1
'
Me.mnuSep1.Index = 1
Me.mnuSep1.Text = "-"
'
' Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(136, 42)
Me.Controls.Add(txtStatut)
Me.Menu = Me.mainMenu1
Me.Name = "Form1"
Me.Text = "Menus"
Me.ResumeLayout(False)
End Sub
Зверніть увагу на інструкцію, яка пов’язує меню з формою:
Me.Menu = Me.mainMenu1
5.7. Невізуальні компоненти
Тепер розглянемо низку невидимих компонентів: їх використовують під час проектування, але під час виконання їх не видно.
5.7.1. Діалогові вікна OpenFileDialog та SaveFileDialog
Ми створимо таку програму:
![]() |
Елементи управління такі:
№ | тип | назва | роль |
1 | TextBox багаторядковий | txtTexte | текст, введений користувачем або завантажений із файлу |
2 | Кнопка | btnSauvegarder | дозволяє зберегти текст з пункту 1 у текстовому файлі |
3 | Кнопка | btnCharger | дозволяє завантажити вміст текстового файлу в 1 |
4 | Button | btnEffacer | очищає вміст 1 |
Використовуються два невидимі елементи управління:

Коли їх перетягують із «ToolBox» і розміщують у формі, вони розміщуються в окремій області внизу форми. Компоненти «Dialog» перетягуються з «ToolBox»:

Код кнопки Effacer є простим:
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' очищаємо поле введення
txtTexte.Text = ""
End Sub
Клас SaveFileDialog визначено так:

Він походить від декількох рівнів класів. З-поміж численних властивостей та методів ми виділимо такі:
типи файлів, що пропонуються у випадаючому списку типів файлів діалогового вікна | |
номер типу файлу, запропонованого за замовчуванням у вищезазначеному списку. Починається з 0. | |
папка, яка спочатку пропонується для збереження файлу | |
ім'я файлу резервної копії, вказане користувачем | |
метод, який відображає діалогове вікно резервного копіювання. Повертає результат типу DialogResult. |
Метод ShowDialog відображає діалогове вікно, подібне до наведеного нижче:
![]() |
випадаючий список, сформований на основі властивості Filter. Тип файлу, запропонований за замовчуванням, визначається методом FilterIndex | |
поточна папка, яка визначається InitialDirectory, якщо це властивість було вказано | |
назва файлу, обрана або введена безпосередньо користувачем. Буде доступна у властивості FileName | |
кнопки «Зберегти»/«Скасувати». Якщо використовується кнопка Enregistrer, функція ShowDialog повертає результат DialogResult.OK |
Процедуру збереження можна записати так:
Private Sub btnSauvegarder_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnSauvegarder.Click
' зберігаємо поле введення у текстовий файл
' налаштування діалогового вікна savefileDialog1
saveFileDialog1.InitialDirectory = Application.ExecutablePath
saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
saveFileDialog1.FilterIndex = 0
' відображається діалогове вікно та отримується його результат
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
' отримуємо ім'я файлу
Dim nomFichier As String = saveFileDialog1.FileName
Dim fichier As StreamWriter = Nothing
Try
' відкриваємо файл для запису
fichier = New StreamWriter(nomFichier)
' тут вводиться текст
fichier.Write(txtTexte.Text)
Catch ex As Exception
' проблема
MessageBox.Show("Problème à l'écriture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' закриваємо файл
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- Прив’язуємо вихідну папку до папки, що містить виконуваний файл програми:
- Вказуємо типи файлів, які потрібно відобразити
Зверніть увагу на синтаксис фільтрів: фільтр1|фільтр2|..|фільтрn, де фільтрi = «Текст»|«Шаблон файлу». У цьому випадку користувач матиме можливість вибирати між файлами *.txt та *.*.
- Вказуємо тип файлу, який потрібно відобразити на початку
У цьому випадку користувачеві спочатку будуть показані файли типу *.txt.
- Відображається діалогове вікно, і його результат отримується
If saveFileDialog1.ShowDialog() = DialogResult.OK Then
- Поки діалогове вікно відкрите, користувач не має доступу до головної форми (так зване модальне діалогове вікно). Користувач вказує ім’я файлу для збереження та залишає діалогове вікно, натиснувши кнопку «Зберегти», «Скасувати» або закривши вікно. Результатом методу ShowDialog є DialogResult.OK лише в тому випадку, якщо користувач скористався кнопкою Enregistrer для виходу з діалогового вікна.
- Після цього ім’я файлу, що створюється, тепер міститься у властивості FileName об’єкта saveFileDialog1. Далі відбувається звичайне створення текстового файлу. У нього записується вміст TextBox: txtTexte.Text, при цьому обробляються винятки, що можуть виникнути.
Клас OpenFileDialog дуже схожий на клас SaveFileDialog і походить з того самого роду класів. З цих властивостей та методів ми звернемо увагу на такі:
типи файлів, що пропонуються у випадаючому списку типів файлів діалогового вікна | |
номер типу файлу, запропонованого за замовчуванням у вищезазначеному списку. Починається з 0. | |
папка, яка спочатку відображається для пошуку файлу, що відкривається | |
ім'я файлу, який потрібно відкрити, вказане користувачем | |
метод, який відображає діалогове вікно збереження. Повертає результат типу DialogResult. |
Метод ShowDialog відображає діалогове вікно, подібне до наведеного нижче:
![]() |
випадаючий список, сформований на основі властивості Filter. Тип файлу, що пропонується за замовчуванням, визначається методом FilterIndex | |
поточна папка, задана InitialDirectory, якщо це властивість було вказано | |
назва файлу, обрана або введена безпосередньо користувачем. Буде доступна у властивості FileName | |
кнопки «Відкрити»/«Скасувати». Якщо використовується кнопка Ouvrir, функція ShowDialog повертає результат DialogResult.OK |
Процедуру відкриття можна записати так:
Private Sub btnCharger_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCharger.Click
' завантажуємо текстовий файл у поле введення
' налаштування діалогового вікна openfileDialog1
openFileDialog1.InitialDirectory = Application.ExecutablePath
openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*"
openFileDialog1.FilterIndex = 0
' відображаємо діалогове вікно та отримуємо його результат
If openFileDialog1.ShowDialog() = DialogResult.OK Then
' отримуємо ім'я файлу
Dim nomFichier As String = openFileDialog1.FileName
Dim fichier As StreamReader = Nothing
Try
' відкриваємо файл для читання
fichier = New StreamReader(nomFichier)
' зчитується весь файл і заноситься в TextBox
txtTexte.Text = fichier.ReadToEnd()
Catch ex As Exception
' проблема
MessageBox.Show("Problème à la lecture du fichier (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
Finally
' файл закрито
Try
fichier.Close()
Catch
End Try
End Try
End If
End Sub
- В якості початкової папки задаємо папку, що містить виконуваний файл програми:
- Вказуємо типи файлів, які потрібно відобразити
- Вказуємо тип файлу, який має відображатися на початку
У цьому випадку користувачеві спочатку будуть показані файли типу *.txt.
- Відображається діалогове вікно, і отримується його результат
If openFileDialog1.ShowDialog() = DialogResult.OK Then
Поки діалогове вікно відкрите, користувач не має доступу до головної форми (так зване модальне діалогове вікно). Користувач вказує ім’я файлу, який потрібно відкрити, і виходить із діалогового вікна, натиснувши кнопку «Відкрити», «Скасувати» або закривши вікно. Результатом методу ShowDialog є DialogResult.OK лише в тому випадку, якщо користувач використав кнопку Ouvrir для виходу з діалогового вікна.
- Після цього ім’я файлу, що створюється, тепер міститься у властивості FileName об’єкта openFileDialog1. Далі відбувається звичайне читання текстового файлу. Зверніть увагу на метод, що дозволяє прочитати файл повністю:
- вміст файлу заноситься в TextBox та txtTexte. Обробляються винятки, які можуть виникнути.
5.7.2. Діалогові вікна FontColor та ColorDialog
Продовжуємо попередній приклад, додавши дві нові кнопки:
![]() |
№ | тип | назва | роль |
6 | Кнопка | btnCouleur | для визначення кольору символів у TextBox |
7 | Кнопка | btnPolice | для встановлення шрифту TextBox |
Ми розміщуємо у формі елемент управління ColorDialog та елемент управління FontDialog:

Класи FontDialog та ColorDialog мають метод ShowDialog, аналогічний методу ShowDialog класів OpenFileDialog та SaveFileDialog. Метод ShowDialog класу ColorDialog дозволяє вибрати колір:

Якщо користувач закриває діалогове вікно за допомогою кнопки OK, результатом виклику методу ShowDialog є DialogResult.OK, а вибраний колір зберігається у властивості Color використовуваного об’єкта ColorDialog. Метод ShowDialog класу FontDialog дозволяє вибрати шрифт:

Якщо користувач закриває діалогове вікно за допомогою кнопки OK, результатом методу ShowDialog є DialogResult.OK, а обраний шрифт зберігається у властивості Font використовуваного об’єкта FontDialog. У нас є елементи для обробки кліків на кнопках Couleur та Police:
Private Sub btnCouleur_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCouleur.Click
' вибір кольору тексту
If colorDialog1.ShowDialog() = DialogResult.OK Then
' змінюємо властивість forecolor у TextBox
txtTexte.ForeColor = colorDialog1.Color
End If
End Sub
Private Sub btnPolice_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnPolice.Click
' вибір шрифту
If fontDialog1.ShowDialog() = DialogResult.OK Then
' змінюємо властивість font для TextBox
txtTexte.Font = fontDialog1.Font
End If
End Sub
5.7.3. Таймер
Тут ми пропонуємо написати такий додаток:
![]() |
№ | Тип | Назва | Роль |
1 | TextBox, ReadOnly=true | txtChrono | відображає таймер |
2 | Кнопка | btnArretMarche | кнопка «Старт/Стоп» хронометра |
3 | Таймер | timer1 | компонент, що генерує подію кожну секунду |
Хронометр увімкнено:

Хронометр зупинено:

Щоб щосекунди змінювати вміст TextBox txtChrono, нам потрібен компонент, який генерує подію кожну секунду, яку ми зможемо перехопити, щоб оновити відображення хронометра. Цим компонентом є Timer:

Після встановлення цього компонента у формі (у розділі невидимих компонентів) у конструкторі форми створюється об’єкт типу Timer. Клас System.Windows.Forms.Timer визначено так:

З його властивостей ми розглянемо лише такі:
кількість мілісекунд, через яку генерується подія Tick. | |
подія, що генерується через Interval мілісекунд | |
встановлює таймер у активний (true) або неактивний (false) стан |
У нашому прикладі таймер називається timer1, а timer1.Interval встановлено на 1000 мс (1 с). Отже, подія Tick відбуватиметься щосекунди. Натискання кнопки «Стоп/Пуск» обробляється за допомогою такої процедури:
Private Sub btnArretMarche_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnArretMarche.Click
' увімкнути чи вимкнути?
If btnArretMarche.Text = "Marche" Then
' записування часу початку
début = DateTime.Now
' виводимо її на екран
txtChrono.Text = "00:00:00"
' запускаємо таймер
timer1.Enabled = True
' змінити напис на кнопці
btnArretMarche.Text = "Arrêt"
' кінець
Return
End If '
If btnArretMarche.Text = "Arrêt" Then
' зупинка таймера
timer1.Enabled = False
' змінюємо напис на кнопці
btnArretMarche.Text = "Marche"
' кінець
Return
End If
End Sub
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' минула одна секунда
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
Напис на кнопці «Зупинка/Пуск» може бути або «Зупинка», або «Пуск». Тому необхідно перевірити цей напис, щоб визначити, яку дію слід виконати.
- у разі «Увімкнути» час початку записується у змінну, яка є глобальною змінною об’єкта форми, таймер запускається (Enabled=true), а напис на кнопці змінюється на «Вимкнути».
- У разі «Зупинка» таймер зупиняється (Enabled=false), а напис на кнопці змінюється на «Увімкнути».
Public Class Timer1
Inherits System.Windows.Forms.Form
Private WithEvents timer1 As System.Windows.Forms.Timer
Private WithEvents btnArretMarche As System.Windows.Forms.Button
Private components As System.ComponentModel.IContainer
Private WithEvents txtChrono As System.Windows.Forms.TextBox
Private WithEvents label1 As System.Windows.Forms.Label
' змінні екземпляру
Private début As DateTime
Атрибут début, наведений вище, відомий у всіх методах класу. Залишається обробити подію Tick на об’єкті timer1, яка відбувається щосекунди:
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles timer1.Tick
' минула одна секунда
Dim maintenant As DateTime = DateTime.Now
Dim durée As TimeSpan = DateTime.op_Subtraction(maintenant, début)
txtChrono.Text = "" + durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2")
End Sub
Обчислюємо час, що минув з моменту запуску хронометра. Отримуємо об’єкт типу TimeSpan, який представляє тривалість у часі. Її потрібно відобразити на хронометрі у форматі hh:mm:ss. Для цього використовуємо властивості Hours, Minutes, Seconds об’єкта TimeSPan, які відповідно представляють години, хвилини та секунди тривалості, яку ми відображаємо у форматі ToString("d2"), щоб отримати двоцифрове відображення.
5.8. Приклад IMPOTS
Повернемося до програми IMPOTS, яку ми вже двічі розглядали. Тепер додамо до неї графічний інтерфейс:
![]() |
Елементи управління такі
№ | тип | назва | роль |
RadioButton | rdOui | позначено, якщо одружений | |
RadioButton | rdNon | позначте, якщо не одружений | |
NumericUpDown | incEnfants | кількість дітей платника податків Мінімальне значення = 0, Максимальне значення = 20, Крок = 1 | |
TextBox | txtSalaire | річний дохід платника податків у F | |
TextBox | txtImpots | сума податку до сплати ReadOnly=true | |
Кнопка | btnCalculer | запускає розрахунок податку | |
Кнопка | btnEffacer | повертає форму до початкового стану під час завантаження | |
Кнопка | btnQuitter | для виходу з програми |
Правила роботи
- кнопка «Розрахувати» залишається неактивною, доки в полі «Заробітна плата» немає даних
- якщо під час запуску розрахунку виявляється, що зарплата вказана неправильно, з’являється повідомлення про помилку:

Програма наведена нижче. Вона використовує клас impot, створений у розділі про класи. Частина коду, що автоматично генерується VS.NET, тут не наведена.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
' параметри
Option Explicit On
Option Strict On
' простори імен
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
' клас форми
Public Class frmImpots
Inherits System.Windows.Forms.Form
Private WithEvents label1 As System.Windows.Forms.Label
Private WithEvents rdOui As System.Windows.Forms.RadioButton
Private WithEvents rdNon As System.Windows.Forms.RadioButton
Private WithEvents label2 As System.Windows.Forms.Label
Private WithEvents txtSalaire As System.Windows.Forms.TextBox
Private WithEvents label3 As System.Windows.Forms.Label
Private WithEvents label4 As System.Windows.Forms.Label
Private WithEvents groupBox1 As System.Windows.Forms.GroupBox
Private WithEvents btnCalculer As System.Windows.Forms.Button
Private WithEvents btnEffacer As System.Windows.Forms.Button
Private WithEvents btnQuitter As System.Windows.Forms.Button
Private WithEvents txtImpots As System.Windows.Forms.TextBox
Private components As System.ComponentModel.Container = Nothing
Private WithEvents incEnfants As System.Windows.Forms.NumericUpDown
' таблиці даних, необхідні для розрахунку податку
Private limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Private coeffR() As Decimal = {0D, 0.05D, 0.1D, 0.15D, 0.2D, 0.25D, 0.3D, 0.35D, 0.4D, 0.45D, 0.55D, 0.5D, 0.6D, 0.65D}
Private coeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' об’єкт податку
Private objImpôt As impot = Nothing
Public Sub New()
InitializeComponent()
' ініціалізація форми
btnEffacer_Click(Nothing, Nothing)
btnCalculer.Enabled = False
' створення об’єкта податку
Try
objImpôt = New impot(limites, coeffR, coeffN)
Catch ex As Exception
MessageBox.Show("Impossible de créer l'objet impôt (" + ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error)
' поле введення заробітної плати вимкнено
txtSalaire.Enabled = False
End Try 'try-catch
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
....
End Sub
Private Sub InitializeComponent()
Me.btnQuitter = New System.Windows.Forms.Button
Me.groupBox1 = New System.Windows.Forms.GroupBox
Me.btnEffacer = New System.Windows.Forms.Button
Me.btnCalculer = New System.Windows.Forms.Button
Me.txtSalaire = New System.Windows.Forms.TextBox
Me.label1 = New System.Windows.Forms.Label
Me.label2 = New System.Windows.Forms.Label
Me.label3 = New System.Windows.Forms.Label
Me.rdNon = New System.Windows.Forms.RadioButton
Me.txtImpots = New System.Windows.Forms.TextBox
Me.label4 = New System.Windows.Forms.Label
Me.rdOui = New System.Windows.Forms.RadioButton
Me.incEnfants = New System.Windows.Forms.NumericUpDown
Me.groupBox1.SuspendLayout()
CType(Me.incEnfants, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
....
End Sub 'InitializeComponent
Public Shared Sub Main()
Application.Run(New frmImpots)
End Sub 'Main
Private Sub btnEffacer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnEffacer.Click
' очищення форми
incEnfants.Value = 0
txtSalaire.Text = ""
txtImpots.Text = ""
rdNon.Checked = True
End Sub 'btnEffacer_Click
Private Sub txtSalaire_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtSalaire.TextChanged
' стан кнопки «Розрахувати»
btnCalculer.Enabled = txtSalaire.Text.Trim() <> ""
End Sub 'txtSalaire_TextChanged
Private Sub btnQuitter_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnQuitter.Click
' завершення роботи програми
Application.Exit()
End Sub 'btnQuitter_Click
Private Sub btnCalculer_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles btnCalculer.Click
' Чи правильна заробітна плата?
Dim intSalaire As Integer = 0
Try
' отримання заробітної плати
intSalaire = Integer.Parse(txtSalaire.Text)
' повинно бути >=0
If intSalaire < 0 Then
Throw New Exception("")
End If
Catch ex As Exception
' повідомлення про помилку
MessageBox.Show(Me, "Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error)
' фокус на полі з помилкою
txtSalaire.Focus()
' виділення тексту в полі введення
txtSalaire.SelectAll()
' повернення до візуального інтерфейсу
Return
End Try 'try-catch
' зарплата правильна — розраховується податок
txtImpots.Text = "" & CLng(objImpôt.calculer(rdOui.Checked, CInt(incEnfants.Value), intSalaire))
End Sub 'btnCalculer_Click
End Class
Тут ми використовуємо збірку impots.dll, отриману в результаті компіляції класу impots із розділу 2. Нагадаємо, що цю збірку можна створити в консольному режимі за допомогою команди
Ця команда створює файл impots.dll, який називається збіркою. Цю збірку можна потім використовувати в різних проектах. Тут, у нашому проекті під назвою VS.NET, ми використовуємо вікно властивостей проекту:

Щоб додати посилання (збірку), клацаємо правою кнопкою миші на ключовому блоці «References» вище, вибираємо опцію [Ajouter une référence] і вказуємо збірку [impots.dll], яку ми заздалегідь помістили в папку проекту:
dos>dir
01/03/2004 14:39 9 250 gui_impots.vb
01/03/2004 14:37 4 096 impots.dll
01/03/2004 14:41 12 288 gui_impots.exe
Після включення збірки [impots.dll] у проект клас [impots] стає відомим проекту. До цього він не був відомий. Інший спосіб — включити вихідний код impots.vb у проект. Для цього у вікні властивостей проєкту клацніть правою кнопкою миші на проєкті, виберіть опцію [Ajouter/Ajouter un élément existant] і вкажіть файл impots.vb.















































