Обработка событий мыши
В компонентах Delphi определен ряд событий, связанных с мышью. Основные из них:
OnClick
Щелчок мыши на компоненте и некоторые другие действия пользователя
OnDblClick
Двойной щелчок мыши на компоненте.
OnMouseDown
Нажатие клавиши мыши над компонентом. Возможно распознавание нажатой кнопки и координат курсора мыши.
OnMouseMove
Перемещении курсора мыши над компонентом. Возможно распознавание нажатой кнопки и координат курсора мыши.
OnMouseUp
Отпускание ранее нажатой кнопки мыши над компонентом. Возможно распознавание нажатой кнопки и координат курсора мыши.
OnEnter
Событие в момент получения элементом фокуса в результате манипуляции мышью, нажатия клавиши табуляции или программной передачи фокуса.
OnExit
Событие в момент потери элементом фокуса в результате манипуляции мышью, нажатия клавиши табуляции или программной передачи фокуса.
Наиболее широко используется событие OnClick. Обычно оно наступает, если пользователь щелкнул на компоненте, т.е. нажал и отпустил кнопку мыши, когда указатель мыши находился на компоненте. Но это событие происходит также и при некоторых других действиях пользователя. Оно наступает, если:
• Пользователь выбрал элемент в сетке, дереве, списке, выпадающем списке, нажав клавишу со стрелкой.
• Пользователь нажал клавишу пробела, когда кнопка или индикатор были в фокусе.
• Пользователь нажал клавишу Enter, а активная форма имеет кнопку по умолчанию, указанную свойством Default.
• Пользователь нажал клавишу Esc, а активная форма имеет кнопку прерывания, указанную свойством Cancel.
• Пользователь нажал клавиши быстрого доступа к кнопке или индикатору. Например, если свойство Caption индикатора записано как '&Попужирный' и символ 'П' подчеркнут, то нажатие пользователем комбинации клавиш Alt+П вызовет событие OnClick в этом индикаторе.
• Приложение установило в true свойство Checked радиокнопки RadioButton.
• Приложение изменило свойсто Checked индикатора Check-Box.
• Вызван метод Click элемента меню.
Для формы событие OnClick наступает, если пользователь щелкнул на пустом месте формы или на недоступном компоненте.
Необходимо четко представлять последовательность отдельных событий, наступающих при том или ином действии пользователя. Рассмотрим эти последовательности.
!
Каждое действие пользователя, связанное с нажатием или отпусканием кнопки мыши, приводит к серии последовательно наступающих событий.
Например, рассмотрим простейшее действие пользователя: переключение с помощью мыши фокуса с одного элемента на другой. Последовательность событий мыши в этом случае приведена в таблице
Действие пользователя
Событие
Перемещение курсора мыши в пределах первого компонента
Множество событий OnMouseMove в первом компоненте
Перемещение курсора мыши в пределах формы
Множество событий OnMouseMove в форме
Перемещение курсора мыши в пределах второго компонента
Множество событий OnMouseMove во втором компоненте
Нажатие кнопки мыши
OnExit в первом компоненте
OnEnter во втором компоненте
OnMouseDown во втором компоненте
Отпускание кнопки мыши
OnClick во втором компоненте
OnMouseUp во втором компоненте
События OnMouseMove происходят постоянно в процессе перемещения курсора мыши и даже просто при его дрожании, неизбежном, если пользователь не снимает руки с мыши. Это надо учитывать, и пользоваться этим событием очень осторожно, поскольку оно, в отличие от других, происходит многократно.
В обработчиках событий OnMouseDown и OnMouseUp можно распознать, какая кнопка мыши нажата и в какой точке компонента находится в данный момент курсор мыши.
Если щелчок делается на объекте, который уже находится в этот момент в фокусе, то не происходят события OnExit и OnEnter. В этом случае при нажатии кнопки наступает только событие OnMouseDown, а при отпускании кнопки — события OnClick и OnMouseUp.
Теперь рассмотрим последовательность событий при двойном щелчке на компоненте.
Действие пользователя
Событие
Первое нажатие кнопки мыши
OnMouseDown. Возможно распознавание нажатой кнопки и координат курсора мыши
Первое отпускание кнопки мыши
OnClick
OnMouseUp. Возможно распознавание нажатой кнопки и координат курсора мьгпГи
Второе нажатие кнопки мыши
OnDblClick
OnMouseDown. Возможно распознавание нажатой кнопки и координат курсора мыши
Второе отпускание кнопки мыши
OnMouseUp. Возможно распознавание нажатой кнопки и координат курсора мыши.
Распознавать нажатую кнопку мыши по-прежнему можно только в событиях OnMouseDown и OnMouseUp. Если же надо распознать именно двойной щелчок какой-то определенной кнопкой мыши, то можно, например, ввести некую переменную, являющуюся флагом двойного щелчка, устанавливать этот флаг в обработчике события OnDblClick, а в обработчиках событий OnMouseDown или OnMouseUp проверять этот флаг и, если он установлен, то сбрасывать его и выполнять запланированные действия.
Распознавание источника события,
нажатых кнопок и клавиш, координат курсора
Распознавание источника события
Во все обработчики событий, связанных с манипуляциями мыши (как и во все другие обработчики), передается параметр Sender типа TObject. Этот параметр содержит указатель на компонент, в котором произошло событие. Он не требуется, если пишется обработчик события для одного конкретного компонента. Однако часто один обработчик применяется для нескольких компонентов. При этом какие-то операции могут быть общими для любых источников события, а какие-то требовать специфических действий. Тогда Sender можно использовать для распознавания источника события. Правда, поскольку тип TObject не имеет никаких полезных для пользователя свойств и методов, то объект Sender следует рассматривать как объект одного из производных от TObject типов.
Если необходимо распознать только тип объекта, можно использовать операцию is.
Например if (Sender is TListBox) then . . .
так можно проверить, является ли источник события компонентом типа TListBox.
Если требуется распознать объект по имени или другому свойству, можно использовать операцию as.
Например, if (Sender as TControl).Name = 'Edit1' then ...
так можно проверить, является ли этот компонент компонентом с именем Edit1.
В данном случае можно было бы просто определить, не является ли Sender объектом Edit1:
if (Sender = Edit1) then ...
Операцию as можно также использовать, если надо применить к источнику события некоторый метод.
Например, оператор (Sender as TWinControl).ScaleBy(11,10) ;
увеличивает на 10% размер любого оконного компонента, в котором произошло обрабатываемое событие.
Распознавание нажатых кнопок
Помимо параметра Sender в обработчики событий OnMouseDown и OnMouseUp передаются параметры, позволяющие распознать нажатую кнопку, нажатые при этом вспомогательные клавиши, а также определить координаты курсора мыши. Заголовок обработчика события OnMouseDown или OnMouseUp может иметь, например, следующий вид:
procedure TForm1.Edit1MouseDown (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Параметр Button определяет нажатую в этот момент кнопку мыши.
Тип TMouseButton — перечислимый тип, определяемый следующим образом:
TMouseButton = (mbLeft, mbRight, mbMiddle) ;
mbLeft - нажатие левой кнопки мыши, mbRight — правой, а mbMiddle — средней.
Например, если необходимо, чтобы обработчик реагировал на нажатие только левой кнопки, можно написать: if (Button <> mbLeft) then exit;
Параметр Shift определяет, какие вспомогательные клавиши на клавиатуре нажаты в момент нажатия кнопки мыши.
Тип TShiftState — множество, определенное следующим образом:
TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble) ;
Элементы этого множества соответствуют нажатию клавиш Shift (ssShift), Alt (ssAlt), Ctrl (ssCtrl), а также кнопок: левой (ssLeft), правой (ssRight), средней (ssMiddle).
Информация о нажатых кнопках в параметрах Button и Shift имеет различный смысл.
!
Параметр Button соответствует кнопке, нажимаемой в данный момент, а параметр Shift содержит информацию о том, какие кнопки были нажаты, включая и те, которые были нажаты ранее.
Например, если пользователь нажмет левую кнопку мыши, а затем, не отпуская ее, нажмет правую, то после первого нажатия множество Shift будет равно [ssLeft], а после второго — [ssLeft, ssRight]. Если до этого пользователь нажал и не отпустил какие-то вспомогательные клавиши, то информация о них также будет присутствовать в множестве Shift.
Так как Shift является множеством, проверять наличие в нем тех или иных элементов надо операцией in.
Например, если необходимо прореагировать на событие, заключающееся в нажатии левой кнопки мыши при нажатой клавише Alt, можно использовать оператор:
if (Button = mbLeft) and (ssAlt in Shift) then ...
Замечание. Здесь условие (Button = mbLeft) можно заменить эквивалентным ему условием
if (ssLeft in Shift) ...
Аналогичные параметры Button и Shift передаются и в обработчик события OnMouseUp. Отличие только в том, что параметр Button соответствует не нажимаемой в данный момент, а отпускаемой кнопке. Параметр Shift передается также в обработчик события OnMouseMove, так что и в этом обработчике можно определить, какие клавиши и кнопки нажаты.
Распознавание координат курсора
Во все события, связанные с мышью, передаются также координаты курсора Х и Y.
Эти параметры определяют координаты курсора в клиентской области компонента. Благодаря этому можно обеспечить различную реакцию в зависимости от того, в какой части клиентской области расположен курсор.
В событие OnMouseDown компонента (формы) можно ввести обработчик, в котором можно анализировать координаты курсора, например
if (Y < 120)
then if (X < 160) then ...
else if (X < 270) then ...