МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Практическая работа по теме 9. Объектноориентированное программирование События формы. События нажатия клавиш на клавиатуре. События, возникающие при нажатии кнопок мыши. Программирование и использование событий в собственном классе. Динамическое подключение событий с помощью метода AddHandler. Обработка нескольких событий в одном методе. Практическая работа по теме 9. Объектно-ориентированное программирование .................1 Задание 1. События форм .........................................................................................................1 Задание 2. События нажатия клавиш на клавиатуре .............................................................4 Задание 3. События MouseDown, MouseUp и MouseMove....................................................7 Задание 4. События собственного класса ...............................................................................8 Задание 5. Динамическое подключение событий с помощью метода AddHandler ..........13 Задание 6. Обработка нескольких событий в одном методе ...............................................15 Задание 7. Создание поля со списком, поддерживающего автоматическое дополнение текста при вводе (практический пример использования обработчиков событий) ...........16 Задание 1. События форм Задача Научиться писать обработчики System.Windows.Forms.Form. событий для объектов класса Решение Познакомить с событиями, поддерживаемыми формами и событийной моделью приложения. Обсуждение Чтобы отредактировать или создать обработчик любого события, в том числе и события, поддерживаемого объектами класса System.Windows.Forms.Form, необходимо в списках Class Name и Method Name, раскрывающихся в окне программного кода, выбрать соответствующие имя объекта и название события (рис. 1). В случае написания обработчика событий для формы в списке Class Name следует выбирать позицию Form Events, а в списке Method Name следует выбрать одно из событий, поддерживаемых объектом Form. После выбора из списков объекта и события в области ввода программного кода автоматически появляется описание заголовка процедуры обработчика события (сигнатуры процедуры обработки выбранного события), в который следует вписать текст программы для обработки выбранного события. Например, для обработки события Closing для Form1 будет представлена следующая сигнатура: Private Sub Form1_Closing(ByVal sender As Object, ByVal e As МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE System.Windows.Forms.PaintEventArgs) Handles Form1.Closing Заголовок процедуры обработчика события включает имя процедуры, состоящее из имени объекта и имени события, записанного через префикс (имя процедуры можно изменить); описания объекта (ByVal sender As Object), которому принадлежит событие; параметра e (ByVal e As System.EventArgs), значения свойств которого можно анализировать при написании обработчика события; директивы компилятору по выполнению события, имеющей следующий синтаксис: Handles имя объекта.имя события. Событий, поддерживаемых объектами класса System.Windows.Forms.Form, довольно много, рассмотрим наиболее важные из них. Рис. 1. Создание обработчика событий формы Начнем с события Load, которое происходит при открытии (инициализации) формы. Событие обычно используется для установки МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE начальных значений элементов управления, расположенных на форме, размеров и местоположения самой формы, другими словами, для инициализации формы. Самостоятельно Ваших знаний вполне достаточно, чтобы полностью самостоятельно написать обработчик события при загрузке Windows-формы, имеющей любые элементы управления, например, списки, текстовые поля, элементы управления для графического вывода и так далее. Напишите обработчик события Form_Load, позволяющий инициировать элементы интерфейса вашей формы. Событие Closed происходит при закрытии формы. Событие обычно используется для сохранения различных конфигураций или настроек пользователя, например, месторасположения формы, ее размеров. Это позволяет пользователю размещать окна приложения там, где ему удобнее с ними работать. Событие Closing происходит при попытке закрыть форму. Обычно его используют, чтобы убедиться, что пользователь действительно хочет закрыть форму. Чтобы иметь возможность отменить закрытие формы, в процедуру обработчик события Closing передается параметр e. Установка значения свойства Cancel этого параметра в True приведет к отмене закрытия формы: e.Cancel=True. Самостоятельно Используя свойства формы Left, Top, Height, Width, которые определяют соответственно положения левого верхнего угла формы на экране (в пикселах), высоту и ширину формы, напишите обработчик события Closed. Событие Paint решает проблему возможных искажений отображения статической графики при перекрывании формы другой формой. Решение проблемы возможно размещением всего кода рисования в обработчике события Paint. Например, программный код, размещенный в обработчике события Paint для Form1, позволит минимизировать искажения при перерисовке изображение в форме. Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint Самостоятельно Используя обработчик события Paint для вашей Windows-формы, перепишите загрузку графических изображений в форму и элемент управления PictureBox. Откройте одновременно две формы и МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE наблюдайте эффекты перерисовки изображений при сокрытии или минимизации формы с графическим объектом. Задание 2. События нажатия клавиш на клавиатуре Задача Исследовать события KeyDown, KeyUp, KeyPress, происходящие при вводе данных с клавиатуры. Решение Использовать события KeyDown, KeyUp, KeyPress для создания событийного интерфейса пользователя. Обсуждение Клавиатура является одним из основных источников событий, происходящих в Windows-формах. События KeyDown, KeyUp и KeyPress происходят при нажатии клавиш на клавиатуре. Событие KeyPress генерируется после получения нажатия клавиши, но до отображения символа. Событие происходит при нажатии на любую из буквенных или цифровых клавиш кроме клавиш Ctrl, Alt, Caps Lock, F1-F10. В процедуру обработчик события передается параметр е, содержащий два важных свойства – KeyChar и Handled. В первом из них передается символ, соответствующий нажатой клавише, с помощью второго можно уведомить систему о том, что событие KeyPress обработано и не следует вызывать другие обработчики этого события. Таким образом, в процедуре обработчике события KeyPress, например, можно анализировать нажатую клавишу. 1. Добавьте Windows-форму в ваш проект. Можно не размещать в ней никаких элементов управления. 2. Перейдите в режим кодирования формы и создайте обработчик события KeyPress формы со следующим программным кодом: Private Sub Form7_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress If e.KeyChar >= "a" And e.KeyChar <= "z" Then MsgBox(e.KeyChar) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Рис. 2. Перехват нажатых клавиш 3. Запустите проект и обратите внимание на то, что состояние клавиш Shift и Caps Lock влияет на символ, поступающий в процедуру обработчик события. Например, при нажатии Shift+H в процедуру поступает символ H, он не будет отображен, так как отображаются только строчные буквы a-z (рис. 2). Использование свойства Handled рассмотрим на следующем примере. 4. Теперь разместите в вашей форме элемент управления TextBox (рис. 2). 5. Создайте обработчик события KeyPress для формы, аналогичный обработчику из предыдущего упражнения. При запуске проекта вы увидите, что прежнего эффекта не наблюдается – любой вводимый символ просто отображается в окне ввода TextBox1. Это происходит потому, что при загрузке формы элемент TextBox1 становится активным, и все нажатые клавиши на клавиатуре генерируют событие KeyPress, связанное с активным элементом TextBox1, а не с формой. Конечно, можно написать еще один обработчик события KeyPress теперь уже для TextBox1, но, во-первых, тогда это придется делать для каждого элемента управления, находящегося на форме, вовторых, алгоритм работы приложения становится довольно сложным, не прозрачным. Лучшее решение состоит в том, чтобы воспользоваться свойством KeyPreview формы Form1, значение которого следует установить в True. 6. Установка свойства KeyPreview в True приведет к тому, что перед вызовом обработчиков событий KeyDown, KeyUp и KeyPress для элементов управления, находящихся на форме, будут вызваны соответствующие обработчики событий самой формы. Теперь окно MsgBox будет отображать каждый нажатый символ, но остается еще одна тонкость: первый введенный символ все еще МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE выводится в TextBox1 и одновременно в MsgBox, последующие – только в MsgBox. 7. Для устранения этого нежелательного эффекта необходимо в процедуре обработчика события KeyPress установить значение параметра e.Handled=True. Теперь форма будет перехватывать все нажатые клавиши – окно ввода останется пустым и при первом и при последующих нажатиях клавиш. Событие KeyPress не отслеживает нажатие клавиш Ctrl, Alt, Caps Lock, F1-F10. События KeyDown и KeyUp происходят при нажатии любых клавиш. Параметр e имеет свойства Alt, Control, Handled и Shift, которые равны True, в случае нажатия соответственных клавиш. Параметр e имеет также свойство KeyCode, которое содержит код нажатой клавиши. Обработчики событий, запрещающие ввод нежелательных символов, например, цифр, проще всего, реализовать, используя общие методы класса Char. Char – это простой размерный тип, представляющий единственный символ. Получить подробную информацию о символе позволяют общие методы типа Char: IsDigit возвращает True, если символ – цифра от 0 до 9; IsNumber возвращает True, если символ –шестнадцатеричная цифра от 0 до F; IsLetter возвращает True, если символ – буква от A до Z; IsLetterOrDigit возвращает True для алфавитно-цифрового символа (A-Z или 0-9); IsLower и IsUpper возвращают True в зависимости от регистра символа; IsPunctuation возвращает True, если символ является знаком пунктуации; IsSymbol возвращает True, если символ классифицируется как символ (symbol); IsWhiteSpace возвращает True, если символ является символом пробела. 8. Добавьте в вашу форму командную кнопку и процедуру обработки события щелчка по ней. Следующий фрагмент кода просматривает текстовое окно и подсчитывает число алфавитноцифровых символов в нем (рис. 3). Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim STR As String = TextBox1.Text Dim Count As Integer Dim Letter As Char For Each Letter In STR If Char.IsLetterOrDigit(Letter) Then Count += 1 МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Next MsgBox(Count) End Sub Рис. 3. Использование класса Char Самостоятельно 1. Создайте приложение для ввода в текстовое окно русского текста. При вводе должен проводиться анализ текста и при попытке ввести латинскую букву должно появляться сообщение об ошибке. 2. Создайте текстовой поле, которое будет отвергать ввод любых символов, кроме цифр и десятичной точки. 3. Создайте Windows-приложение, позволяющее анализировать и сообщать статус клавиш Shift, Alt, Control (нажаты они или отпущены). Приложение может, например, иметь элемент управления Label для вывода информации о нажатых клавишах. Задание 3. События MouseDown, MouseUp и MouseMove Задача Исследовать события MouseDown, MouseUp, происходящие при нажатии одной из кнопок мыши. Решение Использовать события MouseDown, MouseUp, создания событийного интерфейса пользователя. MouseMove, MouseMove для Обсуждение События MouseDown, MouseUp и MouseMove возникают соответственно при нажатии одной из кнопок мыши, отпускании ранее нажатых кнопок мыши или при движении указателя мыши над формой. Процедуре обработчику любого из этих событий передается параметр МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE е, содержащий координаты указателя мыши (e.X и e.Y) и состояние кнопок. Координаты отсчитываются в пикселах относительно левого верхнего угла формы. Добавьте в ваш проект Windows-форму. Напишите следующие обработчики событий: Dim Moving As Boolean = False Dim MouseOldX, MouseOldY As Integer Private Sub Form7_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown If e.Button = MouseButtons.Left Then Moving = True MouseOldX = e.X MouseOldY = e.Y End If End Sub Private Sub Form7_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp If e.Button = MouseButtons.Left Then Moving = False End Sub Private Sub Form7_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove If Moving Then Left = Left + e.X - MouseOldX Top = Top + e.Y - MouseOldY End If End Sub Самостоятельно Реализуйте следующий алгоритм в Windows-приложении: при нажатии правой кнопки мыши можно перемещать форму, у которой нет рамки и заголовка, то есть перемещение выполняется при опускании мыши на любой свободный от элементов управления участок формы. Выключение рамки у формы выполняется установкой свойства FormBorderStyle=None. Задание 4. События собственного класса Задача Научиться инкапсулировать описание событий в собственные классы. Передать данные в нестандартном событии. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Решение Описать класс с событиями. Создать аргумент собственного события в виде класса, производного от System.EventArgs, добавить к нему нужную информацию и объявить событие. Для отправки события использовать метод RaiseEvent. Обсуждение Для инкапсуляции событий в собственный класс достаточно в классе при помощи модификатора Event объявить имя и сигнатуру процедур обработки соответствующих событий, а затем в тех местах, где они должны быть сгенерированы, расположить оператор RaiseEvent, в качестве параметра которого и указать сгенерированное событие. 1. Создадим иерархию классов на основе класса Person. Public Class Person Public FirstName As String Public LastName As String Private _FullName As String Public Sub New() End Sub Public Sub New(ByVal FirstName As String, ByVal Lastname As String) Me.FirstName = FirstName Me.LastName = Lastname _FullName = FirstName & " " & Lastname End Sub Public Overrides Function ToString() As String Return FirstName & " " & LastName End Function Public ReadOnly Property FullName() As String Get Return _FullName End Get End Property End Class 2. Добавим в проект класс Client. Класс не поддерживает событий, является родительским классом для класса ClientWithEvent, поддерживающего события. Public Class Client Inherits Person Private m_Account As Long Public Sub New() MyBase.New() End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Public Sub New(ByVal FirstName As String, ByVal LastName As String) MyBase.New(FirstName, LastName) End Sub Public Sub New(ByVal FirstName As String, ByVal LastName As String, ByVal ValueAccount As Long) MyBase.new(FirstName, LastName) m_Account = ValueAccount End Sub Public Property Account() As String Get Return m_Account End Get Set(ByVal Value As String) m_Account = Value End Set End Property Public Sub Deposite(ByVal value As Long) m_Account += value End Sub Public Sub Withdraw(ByVal value As String) If value <= m_Account Then m_Account -= value End If End Sub Public Overrides Function ToString() As String Return FirstName & " " & LastName & " " & m_Account.ToString End Function End Class 3. Рассмотрим описание класса, поддерживающего события. Пусть класс ClientWithEvent генерирует два события. Первое из них (BigBucksDeposite) генерируется, когда клиент кладет на счет более 10,000 денежных единиц, а второе (GetOff) – когда клиент пытается снять больше денег, чем имеет на счету. Обработчики этих событий будут иметь два параметра. Первый параметр дает ссылку на объект, сгенерировавший событие, а второй (объект MyEventArgs) инкапсулирует в себе информацию о событии. 4. Создадим класс MyEventArgs, как класс наследник стандартного класса EventArgs. Ниже приводится описание класса МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE MyEventArgs, который имеет свойство m для хранения суммы денег и конструктор. Public Class MyEventArgs Inherits EventArgs Private m As Long Sub New(ByVal value As Long) MyBase.New() Me.value = value End Sub Public Property value() As Long Get Return m End Get Set(ByVal V As Long) m=V End Set End Property End Class 5. Рассмотрим описание класса, поддерживающего события. Обратите внимание на следующие ключевые слова #Region #End Region. – в .NET для структурной группировки кода используются эти ключевые слова. Эти операторы не воспринимаются компилятором, но информируют среду разработки, что помеченный код, может быть, свернут при его изображении. Public Class ClientWithEvent Inherits Client #Region "Events Declaration" Описание сигнатуры событий. При наличии собственного класса MyEventArgs, описывающего информацию о событии, в описании сигнатуры обработчика события следует создавать объект е, как экземпляр собственного класса (ByVal sender As ClientWithEvent, ByVal e As MyEventArgs). Public Event BigBucksDeposite(ByVal sender As ClientWithEvent, ByVal e As MyEventArgs) Public Event GetOff(ByVal sender As ClientWithEvent, ByVal e As MyEventArgs) #End Region Public Sub New(ByVal Firstname As String, ByVal Lastname As String, ByVal ValueAccount As Long) MyBase.New(Firstname, Lastname, ValueAccount) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Опишем метод, посылающий событие при наступлении некоторого условия Public Shadows Sub Deposite(ByVal value As Long) MyBase.Account += value If value > 10000 Then Dim e As MyEventArgs = New MyEventArgs(value) RaiseEvent BigBucksDeposite(Me, e) End If End Sub Опишем метод, генерирующий другое событие Public Shadows Sub Withdraw(ByVal value As Long) If value <= MyBase.Account Then MyBase.Account -= value Else Dim e As MyEventArgs = New MyEventArgs(value) RaiseEvent GetOff(Me, e) End If End Sub End Class 6. После того, как класс, генерирующий события, создан, настало время протестировать его. Объект класса ClientWithEvent может быть описан как поддерживающий события, так и без них Public Class Form1 Inherits System.Windows.Forms.Form Опишем объект класса ClientWithEvent с событиями Public WithEvents c As ClientWithEvent Напишем процедуры обработчики событий. Очень четко соблюдайте синтаксис описания объекта и события Sub Client_BigBucksDeposite(ByVal sender As ClientWithEvent, ByVal e As MyEventArgs) Handles c.BigBucksDeposite MsgBox("Хороший вклад " & e.value & " - так держать!!!!!") End Sub Sub Client_GetOff(ByVal sender As ClientWithEvent, ByVal e As MyEventArgs) Handles c.GetOff MsgBox("Прощай, столько " & e.value & " денег - у тебя нет!!!") End Sub 7. Наконец, вызовем метод объекта, в котором событие может произойти Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click c = New ClientWithEvent("Табуреткин", "Вася", 20000) MsgBox(c.ToString) МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE c.Deposite(1000000) MsgBox(c.ToString) c.Withdraw(1000000000) End Sub End Class Экземпляр класса, который может производить события, должен быть объявлен с помощью ключевого слова WithEvents. Далее в программе описаны процедуры обработки событий, имеющие объявленную сигнатуру и обязательное слово Handles, после которого специфицируется объект и событие. Самостоятельно Для класса Triangle, описывающего геометрическую фигуру треугольник, объявите событие, генерирующее сообщение о невозможности создания объекта класса Triangle, в случае если нарушено соотношение сторон треугольника a+b>c. Задание 5. Динамическое подключение событий с помощью метода AddHandler Задача Рассмотреть, как в клиентском классе выполняется обработка событий с применением метода AddHandler. Решение Применить динамическое связывание объекта с событием методом AddHandler. Сравнить синтаксис динамического связывания с обычным связыванием события и объекта, его поддерживающего. Обсуждение 1. Создайте Windows-форму. Разместите в ней две командные кнопки (рис. 4). 2. В классе EventClass определите два события: FirstEvent и SeconEvent. Событие SecondEvent соответствует общепринятой схеме описания событий, согласно которой в первом параметре передается ссылка на объект, инициировавший событие. Событие FirstEvent эту схему игнорирует. Public Class EventClass Public Event FirstEvent(ByVal myData As Integer) Public Event SecondEvent(ByVal Sender As Object, ByVal myData As Integer) Public Sub Test1() RaiseEvent FirstEvent(5) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Public Sub Test2() RaiseEvent SecondEvent(Me, 5) End Sub End Class На примере этого класса мы рассмотри два варианта обработки событий. 3. Для первой кнопки напишите обработчик события – щелчка по кнопке. Для кнопки генерируется метод Button1_Click, а ключевое слово Handles указывает на то, что VB.NET должен автоматически загрузить код метода Click. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click MsgBox("Обычное связывание с объектом", MsgBoxStyle.Information, "Вызов событий класса") End Sub 4. В коде для кнопки Button2 покажем, что существует несколько возможных подходов к обработке событий. Объекты ec и ec2 определяются по-разному: ec2 описывается обычным образом с ключевым словом withEvents, объект ec имеет динамическое связывание с событием FirstEvent. Dim WithEvents ec2 As New EventClass Dim ec As New EventClass AddHandler ec.FirstEvent, AddressOf EventClass_FirstEvent При написании обработчика события ec2 связывается с функцией Event_Class_SecondEvent при помощи ключевого слова Handles – точно также как событие Button1.Click связывалось с методом Button1_Click. Private Sub EventClass_SecondEvent(ByVal obj As Object, ByVal i As Integer) Handles ec2.SecondEvent MsgBox("Событие SecondEvent: обычное связывание с объектом", MsgBoxStyle.Information, "Вызов событий класса") End Sub 5. Объект ec не определяется с ключевым словом WithEvents, для этого объекта используется динамическое связывание с событием FirstEvent командой AddHandler Private Sub EventClass_FirstEvent(ByVal i As Integer) MsgBox("Событие FirstEvent: динамическое связывание с объектом", MsgBoxStyle.Information, "Вызов событий класса") End Sub При этом сигнатура обработчика события будет выглядеть по-другому, без ключевого слова Handled. 6. Напишем обработчик щелчка по кнопке Button2 и посмотрим, что произойдет при нажатии на Button2 (рис. 4). МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim ec As New EventClass AddHandler ec.FirstEvent, AddressOf EventClass_FirstEvent ec.Test1() ec2.Test2() End Sub Самостоятельно Вернемся к классу ClientWithEvent и применим динамическое связывание событий BigBucksDeposite и GetOff с объектами этого класса. Измените в вашем проекте объявление объектов с событиями на динамическое связывание и напишите другие обработчики для событий, происходящих с объявленными объектами класса ClientWithEven. Рис. 4. События FirstEvent и SecondEvent при обычном и динамическом связывании с объектом Задание 6. Обработка нескольких событий в одном методе Задача Обработать несколько событий при выполнении одного метода. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Решение Научиться формировать сигнатуру обработчика нескольких событий в одном методе. Обсуждение Рассмотрим один из возможных случаев, требующий обработки нескольких событий при вызове одного метода. 1. Воспользуемся формой, разработку которой мы начинали при выполнении задания 5. Откройте форму в режиме дизайнера. Добавьте в форму командную кнопку, назовите ее btnClose. 2. Поместите в форму элемент управления MainMenu, назовите объект mnuFile и присвойте его свойству Text значение File. Добавьте в созданное меню команду Exit, присвоив при этом объекту имя mnuExit. 3. Откройте форму в режиме редактора кода ViewCode и добавьте код обработчика события Click, написанный следующим образом: Private Sub Form8_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClose.Click, mnuExit.Click Me.Close() End Sub 4. Запустите проект и убедитесь, что форма закрывается как при щелчке по командной кнопке Close, так и при выборе команды меню Exit. Самостоятельно Примените рассмотренную технологию обработки нескольких событий в рамках выполнения одного метода для проекта из задания 5. Попробуйте связать оба события BigBucksDeposite и GetOff класса ClientWithEvent с методом, который выводит на экран приветствие пользователю, выполняющему операции по вкладу или снятию денег. Задание 7. Создание поля со списком, поддерживающего автоматическое дополнение текста при вводе (практический пример использования обработчиков событий) Задача Создать поле со списком (ComboBox), которое анализирует список элементов и автоматически дополняет вводимую пользователем информацию. Решение Реализовать простое автоматическое дополнение поля со списком можно в обработчике события KeyPress. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Обсуждение Приложения могут включать элементы управления, поддерживающие автодополнение. Такие элементы могут дополнять водимые значения, опираясь на список недавних выбранных вариантов (как делает Microsoft Excel при вводе значений ячеек), или отображать раскрывающийся список похожих вариантов (как делает Internet Explorer при вводе URL). Чтобы создать простое поле со списком, поддерживающее автоматическое дополнение текста, вы можете реализовать обработчики событий KeyPress и TextChanged, отыскивая совпадающие элементы в соответствующем списке и затем дополняя значение до совпадающего элемента. После дополнения значения до совпадающего элемента важно не забыть про выделение символов между текущей точкой вставки и концом текста. Благодаря этому пользователь, продолжив печатать, сможет заменить добавленный текст (рис. 5). Рис. 5. Поле со списком, поддерживающее автоматическое дополнение 1. Добавьте в ваш проект пустую Windows-форму. Разместите на ней элемент управления ComboBox1. 2. Напишите процедуру заполнения списка любыми значениями, например, фамилиям. Используйте для заполнения списка обработчик события загрузки формы Form_Load. Private Sub Form9_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ComboBox1.Items.Add("Дроздов") ComboBox1.Items.Add("Белкин") ComboBox1.Items.Add("Шапкин") ComboBox1.Items.Add("Шубкин") ComboBox1.Text = "" End Sub 3. Для отслеживания нажатия специальной клавиши (в этом случае операция дополнения текста будет пропущена) введите глобальную переменную: Private ControlKey As Boolean = False МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE 4. Напишите обработчик события KeyPress для определения нажатия специальной клавиши Private Sub ComboBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles ComboBox1.KeyPress Получение ссылки на элемент ComboBox, сгенерировавший данное событие Dim Combo As ComboBox = CType(sender, ComboBox) If Asc(e.KeyChar) = Keys.Escape Then Очистка поля ComboBox1.SelectedIndex = -1 ComboBox1.Text = "" ControlKey = True ElseIf Char.IsControl(e.KeyChar) Then ControlKey = True Else ControlKey = False End If End Sub 5. Напишите обработчик события TextChanged для элемента управления ComboBox, в коде которого опишите поиск совпадающего элемента, вставку найденного элемента в поле ввода, выделение добавленного фрагмента Private Sub Combobox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.TextChanged Получение ссылки на элемент ComboBox, сгенерировавший событие Dim Combo As ComboBox = CType(sender, ComboBox) If Combo.Text <> "" And Not ControlKey Then Поиск совпадающего элемента Dim MatchText As String = Combo.Text Dim Match As Integer = Combo.FindString(MatchText) Если совпадающий элемент найден, он вставляется в поле If Match <> -1 Then Combo.SelectedIndex = Match Добавленный текст выделяется, чтобы пользователь. Продолжив печатать, мог его заменить Combo.SelectionStart = MatchText.Length Combo.SelectionLength = Combo.Text.Length - Combo.SelectionStart End If End If End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE 6. Протестируйте созданную форму с элементом управления, поддерживающим автоматическое дополнение текста. Самостоятельно Добавьте в форму гиперссылку, при щелчке которой выполнялось бы некоторое действие (например, загрузка сайта компании Microsoft). Используйте элемент управления LinkLabel. Задайте расположение гиперссылок и напишите обработчик события LinkLabel для определения действия, которое следует предпринять. По умолчанию в ссылку будет включен весь текст. Для изменения текста ссылки найдите в окне Properties свойство LinkArea и запустите специальный редактор гиперссылок (рис. 6). Рис. 6. Задание текста ссылки При генерации события LinkClicked можно выполнить любой программный код, например запуск Internet Explorer (рис. 7): Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked e.Link.Visited = True Dim URL As String = CType(e.Link.LinkData, String) Process.Start(URL) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Рис. 7. Элемент управления LinkLabel