Часть 1. Основы Visual Basiс
На главную самоучителя
08.02.2005
Глава 14.
События. Перехват нажатий кнопок мыши.
Рисование фигур программными методами. Методы Line и Circle.
Скачать исходник примера "Mouse"


Поскольку мышь (она же крыса) является главным разрушительным орудием юзера, нам надо предоставить ему все возможности для пользования ее в мирных целях. Но прежде, чем начать мучать крысу, поговорим о том, что считалось само собой разумеющимся и как-бы не требующим особых пояснений. Это события.

События.

Прежде всего хочу сказать, что ранее, при создании процедуры объекта мы довольствовались тем событием, которое нам предоставлял VB по умолчанию. Например для формы - это загрузка Form1_Load(), для кнопки - щелчок мыши Command1_Click и так далее. Однако, для почти каждого объекта есть довольно-таки большой список и других доступных событий, которые можно посмотреть в правом поле вверху окна кода. То есть, если мы создали процедуру для формы, реагирующую на загрузку формы Form_Load, то щелкнув по полю, где находится надпись Load, мы в выпавшем списке видим еще массу событий и с каждым мы можем создать свою процедуру, например Form_Click, или там Form_MouseMove.
По сути, событие - это машинное прерывание, вызванное пользователем, другой программой, системой или еще чем-нибудь. Таким образом, выполнение процедуры для объекта начинается когда наступает событие этой процедуры.
Почему мы программный код обычно начинаем с процедуры Form_Load? Потому что при загрузке программы наша форма автоматически загружается, и хочешь-нехочешь, наступает событие Load, начинается выполнение процедуры Form_Load, в которой, поэтому, удобно выполнять предварительные действия по подготовке программы к работе: загрузка служебных файлов, установка свойств объектов, присвоение начальных значений переменным и т.п. А уж далее, либо из этой процедуры происходит переход к другим процедурам, либо программа ожидает наступления других событий для объектов, под которые должны быть написаны свои процедуры. Те же процедуры, которые мы писали сами, обзывали, как хотели, не будут выполнятся никогда, пока мы конкретно не вызовем их по имени. Эти процедуры ни с объектом, ни с событием никак не связаны.

Теперь перейдем к тем событиям, которые вызываются непредсказуемым воздействием юзера на мышь.


Private Sub объект_MouseMove ([индекс As Integer,] клавиша As Integer, shift As Integer, x As Single, y As Single)

Возникает при перемешении мыши над объектом.
По значению необязательной переменной индекс можно отследить, над каким элементом массива объектов Control Array (если массив существует) происходит перемещение.
Переменная клавиша указывает состояние всех клавиш мыши, а не указывает на какую-нибудь одну, как при событиях _MouseDown или _MouseUp. Поэтому значения клавиш (1-левая, 2 - правая, 4 - средняя, 0 - никакая) складываются (1+2=3 нажаты левая и правая клавиши мыши одновременно).
Переменная shift возвращает состояние кнопок shift, alt и ctrl в момент нажатия клавиш мыши (1- shift, 2- alt и 4 - ctrl). При удержании больше одной кнопки их значения складываются (ctrl-alt = 4+2=6).
Значения переменных x и y возвращают текущие координаты курсора мыши (x - по-горизонтали, y - по-вертикали) в единицах измерения, заданных свойствами ScaleHeight, ScaleWidth.

Private Sub объект_MouseDown ([индекс As Integer,] клавиша As Integer, shift As Integer, x As Single, y As Single)
и
Private Sub объект_MouseUp ([индекс As Integer,] клавиша As Integer, shift As Integer, x As Single, y As Single)

 

Возникает при нажатии (_MouseDown) или отпускании (_MouseUp) клавиши мыши, при нахождении курсора мыши над объектом.
При этом по значению необязательной переменной индекс можно отследить, над каким элементом массива объектов Control Array (если массив существует) нажата клавиша.
Также позволяет отследить, какая клавиша мыши нажата (не показывает состояние всех клавиш одновременно, как событие _MouseMove), по состоянию переменной кнопка (1- левая клавиша, 2 - правая клавиша, 4 - средняя клавиша).
Переменная shift возвращает состояние кнопок shift, alt и ctrl в момент нажатия клавиш мыши (1- shift, 2- alt и 4 - ctrl). При удержании больше одной кнопки их значения складываются (ctrl-alt = 4+2=6).
Значения переменных x и y возвращают текущие координаты курсора мыши (x - по-горизонтали, y - по-вертикали) в единицах измерения, заданных свойствами ScaleHeight, ScaleWidth.

Private Sub объект_Click() Возникает при щелчке левой или правой клавиши мыши, при нахождении курсора мыши над объектом.
Объекты CheckBox, CommandButton, Listbox или OptionButton реагируют только на щелчок левой клавиши. Кроме того, если у нас существует массив объектов Control Array (см. Главу 13), то введя переменную индекс в объявление процедуры, можно определить, по какому элементу массива щелкнула мышь. В этом случае объявлять процедуру надо так:
Private Sub объект_Click (индекс As Integer).



Индекс
и возвратит номер элемента массива.
Вот пример кода, когда на форме имеется массив Control Array из трех текстбоксов Text1(0), Text1(1) и Text1(2) и текстбокс Text2. При щелчке мышью по одному из элементов Text1 в текстбокс Text2 будет выводится индекс элемента Control Array.
Private Sub Text1_Click(Nomer As Integer)
Text2.Text = "Щелкнуто по номеру" & " " & Nomer
End Sub
При возникновении этого события порождаются события MouseUp и MouseDown.
Чтобы различать нажатия клавиш, надо использовать события MouseUp и MouseDown.


Private Sub объект_DblClick() Возникает при двойном щелчке клавиши мыши, при нахождении курсора мыши над объектом.
Private Sub объект_DblClick (индекс As Integer). Аналогичен событию _Click.

Тут надо помнить один очень важный момент. Порядок наступления событий различен для различных элементов. Нужно следить, чтобы события (время их наступления) не противоречили друг другу. Если написать две процедуры, одну на событие _Click, а вторую - на _DblClick в надежде, что они будут выполнятся в зависимости от наступившего события, то процедура _DblClick не будет выполнятся никогда, поскольку событие _Click наступит раньше, начнется выполнение ее процедуры и на _DblClick можно будет наплевать.

Рассмотрим самое мощное событие - _MouseMove на примере (поскольку остальные события используются аналогично) программки Mouse:
сделаем новый exe-проект и для наших опытов в верхней части формы создадим массив из пяти TextBox'ов Text1(0), Text1(1), Text1(2), Text1(3), Text1(4), и положим один PictureBox. (Рис. 25).


Рисунок 25.

А в нижней части формы расположим шесть лейблов. В первый будем записывать, с каким объектом работает мышь, во второй - состояние клавиш мыши, в третий - состояние кнопок SHIFT-CTRL-ALT, в четвертый и пятый - координаты мыши, а в шестой - номер элемента массива TextBox'ов, с которым работает мышь.


'Объявим пару переменных для записи пометок в лейблах
Option Explicit
Dim ValButton As String
Dim
ValShift As String

'и создадим процедуру для нашей формы с событием _MouseMove и напишем код:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Label1.Caption = "Мышь работает с формой"
'в зависимости от значения Button определяем, какая клавиша мыши нажата
If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If
Label2.Caption = "Значение Button= " & Button & ValButton

'в зависимости от значения Shift определяем, какая комбинация из кнопок SHIFT-CTRL-ALT нажата
If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift
'выводим координаты мыши
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Массива из форм Control Array быть не может"
End Sub


Обратите внимание, что все кнопки и клавиши отслеживаются только тогда, когда мышь движется. Ждать результатов на неподвижной мыши бесполезно.
Теперь, если мы запустим программу, то увидим, что все нажатия кнопок и клавиш, а также изменение координат происходит только тогда, когда курсор мыши находтся над формой. Как только мы перемещаемся на любой объект, TextBox или PictureBox, видимых изменений не происходит. Поскольку мы написали процедуру для формы, над другими объектами она не работает. Кроме того, координаты возвращаются внутри именно того объекта, над которым находится мышь. Т.е., если мышь находится над PictureBox'ом, значит и координаты будут PictureBox'а, а не формы Form1.
Для того, чтобы наша программка работала над всеми объектами, создадим аналогичные процедуры для объектов PictureBox и массива TextBox'ов Text1:

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Label1.Caption = "Мышь работает с PictureBox"
If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If

Label2.Caption = "Значение Button= " & Button & ValButton

If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Массива из PictureBox'ов сейчас нет"
End Sub

Private Sub Text1_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
Label1.Caption = "Мышь работает с массивом TextBox'ов"
If Button = 0 Then
ValButton = " Ни одной клавиши мыши не нажато"
ElseIf Button = 1 Then
ValButton = " Нажата левая клавиша мыши"
ElseIf Button = 2 Then
ValButton = " Нажата правая клавиша мыши"
ElseIf Button = 4 Then
ValButton = " Нажата средняя клавиша мыши"
ElseIf Button = 3 Then
ValButton = " Нажаты левая и правая клавиши мыши"
ElseIf Button = 7 Then
ValButton = " Нажаты все три клавиши мыши"
End If

Label2.Caption = "Значение Button= " & Button & ValButton

If Shift = 0 Then
ValShift = " Ни одна из кнопок не нажата"
ElseIf Shift = 1 Then
ValShift = " Нажата кнопка SHIFT"
ElseIf Shift = 2 Then
ValShift = " Нажата кнопка CTRL"
ElseIf Shift = 4 Then
ValShift = " Нажата кнопка ALT"
ElseIf Shift = 3 Then
ValShift = " Нажаты кнопки SHIFT и CTRL"
ElseIf Shift = 6 Then
ValShift = " Нажаты кнопки ALT и CTRL"
ElseIf Shift = 5 Then
ValShift = " Нажаты кнопки SHIFT и ALT"
ElseIf Shift = 7 Then
ValShift = " Нажаты все три кнопки SHIFT-CTRL-ALT"
End If
Label3.Caption = "Общее состояние кнопок SHIFT-CTRL-ALT - " & Shift & " ;" & ValShift
Label4.Caption = "Координата x= " & X & " твипов"
Label5.Caption = "Координата y= " & Y & " твипов"
Label6.Caption = "Мышь находится над " & "Text1(" & Index & ")"
End Sub

Конечно, все это можно написать короче, используя одну собственную процедуру - ведь код этих процедур почти одинаков, но сейчас так будет яснее.
Теперь нажатия и координаты отслеживаются над всеми объектами, кроме лейблов. Для устранения этого, мы можем в их свойствах поставить значение свойства .Enabled в окне свойств в положение False. Тогда при нахождении курсора мыши над лейблами будут показываться нажатия кнопок и координаты мыши при событии _MouseMove, наступающем для формы. Однако текст в лейблах изменится на серенький.
Скачать исходник программы Mouse можно вверху страницы.

Рисование фигур программными методами.

Теперь я скажу, что рисовать такие фигуры, как круг, овал, прямоугольник, линия можно не только с помощью объекта Shape, но и программно, путем написания операторов. Это очень просто.

Прямоугольник, линия - метод Line.

Для рисования на объекте линии или прямоугольника существует метод Line. Синтаксис его такой

объект.Line [Step] (x1, y1) [Step] (x2, y2), [color], [B][F]
Где

объект это объект на котором рисуется фигура. Если не задан, то используется объект на котором в этот момент установлен фокус.
Step необязательное ключевое слово, устанавливает, что начальная точка прямоугольника - верхний левый угол, (или линии) задается не по абсолютными координатами x1, y1, а относительно текущих координат, определяемых значениями свойств CurrentX и CurrentY.
x1, y1 координаты начальной точки прямоугольника (верхний левый угол) или линии (единицы измерения определяются свойством ScaleMode).
Step необязательное ключевое слово, устанавливает, что конечная точка прямоугольника - нижний правый угол, (или линии) задается не по абсолютыми координатами x2, y2, а относительно координат начальной точки прямоугольника x1,y1.
x2, y2 координаты конечной точки прямоугольника (нижний правый угол) или линии (единицы измерения определяются свойством ScaleMode).
color определяет цвет линии или прямоугольника. Может задаваться как RGB - в формате шестнадцатиричного числа VB (&HFF0033), либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно использовать функции RGB или QBColor. Если не задан, цвет устанавливается тот, что задан свойством .ForeColor.
B определяет, что будет прямоугольник. Если его опустить, рисоваться будет линия.
F определяет, что прямоугольник будет закрашен тем же цветом, что и его границы (заливка). Используется с опцией B.

Таким образом, чтобы нарисовать линию, например, в объекте Picture1, можно использовать такой код:

Private Sub Form_Load()
'задаем единицы измерения пиксели
Picture1.ScaleMode = vbPixels
'устанавливаем свойство AutoRedraw в True, а то нашего рисования видно не будет

Picture1.AutoRedraw = True
'ширину лини устанавливаем в 3 пикселя
Picture1.DrawWidth = 3
'ставим цвет в свойстве ForeColor в фиолетовый
Picture1.ForeColor = &HFF00FF
'рисум линию с начальной координатой X1=10, Y1=10 и конечной X2=150, Y2=150 пикселей
'поскольку цвет не задаем, линия будет фиолетовой по свойству ForeColor

Picture1.Line Step(10, 10)-(150, 150)
End Sub


Если мы в оператор Picture.Line добавим B, то у нас получится прямоугольник (в общем-то квадрат)
Picture1.Line (10, 10)-(150, 150), , B
Чтобы изменить цвет линий, например, на красный, независимо от .ForeColor:
Picture1.Line (10, 10)-(150, 150), vbRed, B
И наконец можем залить наш квадратик
Picture1.Line (10, 10)-(150, 150), vbRed, BF

Ключевое слово Step можно использовать, если нужно привязаться к постоянно меняющимся значениям свойств .CurrentX и .CurrentY. Так, например, мы можем нарисовать наш квадратик там, куда щелкнем мышкой.

Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &HFF00FF
End Sub

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Picture1.Cls 'очищаем Picture1 перед каждым кликом
Picture1.CurrentX = X
Picture1.CurrentY = Y
Picture1.Line Step(0, 0)-Step(150, 150), vbRed, B
End Sub

Окружность, эллипс, дуга - метод Circle.

Для рисования на объекте окружности, эллипса или дуги применяется метод Circle. Его синтаксис:

объект.Circle [Step] (x, y), радиус, [color, start, end, aspect],
Где

объект это объект на котором рисуется фигура. Если не задан, то используется объект на котором в этот момент установлен фокус.
Step необязательное ключевое слово, устанавливает, что центр окружности задается не по абсолютным координатам x, y, а относительно текущих координат, определяемых значениями свойств CurrentX и CurrentY.
x, y координаты центра окружности (единицы измерения определяются свойством ScaleMode)
радиус радиус окружности, эллипса ил дуги (единицы измерения определяются свойством ScaleMode).
color определяет цвет окружности, эллипса или дуги. Может задаваться как RGB - в формате шестнадцатиричного числа VB (&HFF0033), либо цветом, определяемым ключевыми словами Visual Basic (vbRed). Можно использовать функции RGB или QBColor. Если не задан, цвет устанавливается тот, что задан свойством .ForeColor.
start, end при создании дуги задают начальное и конечное значение угла дуги в радианах (от -2pi до 2pi)
aspect коэффициент сжатия эллипса. По умолчанию равен 1,0, т.е. сжатия нет, выводится окружность.

Ну-с, опять в нашем Picture1 рисуем окружность. Все происходит аналогично методу .Line

Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &HFF00FF
Picture1.Circle (200, 120), 70
End Sub


Мы нарисовали фиолетную окружность с центром в точке X=200, Y=120 и и диаметром 70 пикселей.
Теперь превратим ее в эллипс синего (&HFF0000) цвета. Коэффициент aspect установим в 0,5, т.е сожмем окружность в 2 раза.

Picture1.Circle (200, 120), 70, &HFF0000, , , 0.5

Попробуем теперь нарисовать дугу окружности. Коэффициент эллипcности убираем (дуга эллипса - некрасиво). Цвет определим зеленый (&H8000&)
Picture1.Circle (200, 120), 70, &H8000&, 0, 1

А вот пример маленького кода, где мы можем использовать "мышиные" события и рисование фигур. Эта программка рисует окружность, причем радиус и положение задается нажатием клавиши мыши. Когда клавиша отпускается, окружность фиксируется.

Option Explicit
Dim OldX As Single
Dim
OldY As Single
Private Sub Form_Load()
Picture1.ScaleMode = vbPixels
Picture1.AutoRedraw = True
Picture1.DrawWidth = 3
Picture1.ForeColor = &H8000&
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
OldX = X
OldY = Y
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim Center As Long
Picture1.CurrentX = X
Picture1.CurrentY = Y
If Button = 1 Then
Picture1.Cls
Picture1.Circle Step(OldX, OldY), Sqr((X - OldX) ^ 2 + (Y - OldY) ^ 2), &H8000&
Center = Sqr((X - OldX) ^ 2 + (Y - OldY) ^ 2)
End If
End Sub

Этот пример можно скачать отсюда.

Copyright © 2005 4us

Сайт создан в системе uCoz