События клавиатуры

Три события клавиатуры инициируются в тех же ситуациях, что и их аналоги из прежних версий VB.

По аналогии с VB6 событие KeyDown инициируется раньше события KeyPress, которое, в свою очередь, предшествует KeyUp. Событие KeyPress использует объект KeyPressEventArgs, в свойстве KeyChar которого передается информация о нажатой клавише. Например, следующий фрагмент выводит окно сообщения в том случае, если введенный символ не является цифрой:

Private Sub TextBoxl_KeyPress(ByVal sender As Object._

ByVal e As System.Windows.Forms.KeyPressEventArgs)

Handles TextBoxl.KeyPress

If e.KeyChar < "0" Or e.KeyChar > "9" Then

MsgBox("only digits allowed")

End If

End Sub

События KeyDown и KeyUp, как и в VB6, могут использоваться для проверки клавиш-модификаторов (таких, как Ctrl и Alt). Класс KeyEventArgs, передаваемый этим событиям, обладает несколько большими возможностями, чем класс KeyPressEventArgs события KeyPress. Класс KeyEventArgs содержит свойство KeyData, в котором при помощи перечисляемого типа Key передается полная информация о комбинациях клавиш и о состоянии клавиш-модификаторов в момент нажатия. Свойства Modi f i ers и Shi ft позволяют узнать об одновременном нажатии трех клавиш (Alt+ +Shift+другая клавиша). Например, следующая команда проверяет, была ли нажата клавиша-модификатор Alt: If e.Modifiers =Keys.Alt Then

Если вас не интересуют такие мелочи, как различия между левой и правой клавишей Shift, удобнее воспользоваться свойствами Control Shift и Alt класса KeyEventArgs.

К сожалению, значения свойств KeyChar и KeyData нельзя сбросить, поскольку они доступны только для чтения [ Возможно, этот недочет будет исправлен в окончательной версии. ]. Впрочем, введенный символ можно «поглотить» и тем самым предотвратить его появление в элементе; для этого свойству Handled объекта события задается значение True. Пример:

If e.KeyChar < "0" Or e.KeyChar >"9" Then

e.Handled = True

End If

В результате неверный символ не появится в текстовой поле.

 

События проверки

В .NET вместо одного события проверки существуют целых два: Validating и Validated. Событие Validating инициируется перед утратой фокуса элементом. Например, следующий фрагмент гарантирует, что пользователь не оставит текстовое поле пустым:

Public Sub TextBoxl_Validating(ByVa1 sender As Object.

ByVal e As System.ComponentModel.CancelEventArgs)

Handles TextBoxl.Validating

' Если текстовое поле не содержит символов, отменить передачу фокуса

If TextBoxl.Text.Trim = String.Empty Then e.Cancel = True

End Sub

Команда e.Cancel = True отменяет передачу фокуса от текстового поля другому элементу, если в поле нет ни одного символа.

С другой стороны, событие Val idated инициируется после утраты фокуса элементом, но до передачи его другому элементу. Таким образом, в обработчике события Validated можно обновить состояние других элементов формы.

Если свойство CausesValidation элемента равно False, события Validating и Validated не инициируются.

 

Графика: GDI+

Графическое программирование в .NET Framework полностью отличается от всего, что было реализовано в прежних версиях VB. Знакомые графические команды (частично позаимствованные еще из QuickBasic) исчезли. Из числа принципиальных изменений также следует обратить внимание на отсутствие свойства AutoRedraw или его аналогов. В прежних версиях VB свойство AutoRedraw, равное True, избавляло программиста от необходимости программировать процедуру события Pal nt для того, чтобы обеспечить восстановление графического изображения в элементе.

Программирование графики в VB .NET основано на концепции графического контекста — отдаленного родственника контекстов устройств Windows GDI. Любопытная подробность: новая система называется GDI+, хотя с GDI она имеет очень мало общего.

У программистов с опытом работы в GDI переход на GDI+ часто вызывает шок, поскольку графический вывод в .NET происходит без сохранения состояния. Иначе говоря, каждая графическая команда должна содержать полную информацию о выполняемой операции. Скажем, если вы использовали черную кисть в первой строке программы и хотите снова воспользоваться ею во второй строке, необходимо указать графической системе, что операция должна выполняться черной кистью. GDI+ «не помнит» об операциях, выполнявшихся ранее.

Классы GDI+ находятся в пространствах имен System.Drawing, System.Drawing. Drawing2D, System. Drawing. Imagi ng и System. Drawing. Text [ Каждое из этих пространств имен заслуживает отдельной книги, и здесь мы ограничимся лишь кратким упоминанием. ]. Эти пространства имен входят в сборку System.Drawing, ссылка на которую создается автоматически при выборе типа приложения Windows Application в диалоговом окне New Project.

Большая часть графического вывода в GDI+ осуществляется переопределением процедуры [ Это не событие, хотя в конечном счете перерисовка и приводит к |ызову события OnPaint базового класса Form. ]OnPaint формы или элемента. Процедура OnPaint играет столь же важную роль, как и в прежних версиях VB: она обеспечивает восстановление изображения при временном скрытии или свертывании формы. Сигнатура этой важной процедуры выглядит следующим образом: Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

Вывод осуществляется на графической поверхности GDI+, представленной экземпляром класса Graphics. Процедура OnPaint класса Form инкапсулирует такую поверхность в виде значения свойства e.Graphics.

Хотя любая форма или элемент (в том числе и PictureBox) с поддержкой вывода позволяет получить доступ к своему графическому содержимому при помощи вызова ControlName.CreateGraphics, будьте очень внимательны, если это происходит за пределами процедуры Paint. Между выводом в графическом контексте, полученным вызовом e.Graphics в процедуре OnPaint и написанием кода, использующего CreateGraphics, существуют тонкие различия. Мы столкнулись с этой проблемой при создании программы вывода всех шрифтов (см. ниже).

 

Простейший вывод

Рассмотрим очень простой пример графического вывода. Следующая программа выводит растровый файл sample.bmp (находящийся в каталоге \bin решения) в левом верхнем углу формы:

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

MyBase.OnPaint(e)

Dim g As Graphics

g = e.Graphics()

g.Draw!mage(New Bitmap("sample.bmp"). 0. 0)

g.Dispose()

End Sub

Обратите внимание на вызов Dispose в строке, выделенной жирным шрифтом. Поскольку сборщик мусора не освобождает графические контексты, привыкайте делать это самостоятельно в конце процедуры Paint.

Напоминаем: если объект поддерживает метод Dispose, этот метод следует вызвать по завершении работы с объектом.

Следующий этап — рисование линий, прямоугольников и других фигур. Перед операциями такого рода следует получить объект пера, который является экземпляром класса System.Drawing.Pen. Самый распространенный конструктор класса Реп имеет следующий синтаксис:

Public Sub New(Color.Single)

Первый параметр определяет цвет пера (и входит в перечисляемый тип System. DrawingColor), а второй определяет толщину пера (другие конструкторы также позволяют задать кисть для заполнения внутренней части объекта). Например, чтобы нарисовать прямоугольник, вы определяете его размеры и вызываете g. DrawRectangle. Результат выполнения следующей программы показан на рис. 8.22:

Protected Overrides Sub OnPaint(ByVa1 e As PaintEventArgs)

MyBase.OnPaint(e)

Dim g As Graphics

g = e.Graphics()

Dim myPen As New PerKColor,Purple. 6)

Dim aRectangle As New Rectangle(Me.ClientRectangle.Width \4,_

Me.ClientRectangle.Height \ 4. . Me.ClientRectangle.Height \2,_

Me.ClientRectangle.Width \ 2))

g.DrawRectangle(myPen,aRectangle)

g.Dispose()

End Sub

Рис. 8.22. Результат вызова DrawRectangle: прямоугольник в рамке толщиной 6 пикселов

 

Вывод текста

Метод DrawString объекта Graphics предназначен для вывода текста. При вызове этого метода задается объект шрифта, цвет, кисть и начальная точка вывода. Например, следующий фрагмент выводит текст «Hello World» — в современных книгах по программированию это превратилось в традицию. При выводе используется текущий шрифт формы, текст выводится фиолетовой кистью на белом фоне:

Protected Overrides Sub OnPaint(ByVal e As _

System.Wi ndows.Forms.PaintEventArgs)

MyBase.OnPaint(e)

Dim g As Graphics = e.Graphics

Dim theColor As Color = Color.Purple

Dim theFont As New Font("Arial", 22._

FontStyle.Bold Or FontStyle.Italic)

Me.BackColor = Col or.White

g.DrawString("Hello World!". theFont.New SolidBrush(theColor). 0, 0)

g.Dispose()

End Sub

Рис. 8.23. Вывод текста «Hello World!» средствами GDI+

В GDI+ полностью поддерживается кодировка Unicode, что позволяет выводить текст на любом языке.