При работе с приложениями Widows часто используется такой прием, когда юзер может нажать над объектом левую кнопку мыши, и не отпуская ее переместить мышь в другое место. При этом образ объекта следует за курсором мыши. При отпускании кнопки объект перемещается в новое место (если это предусмотрено программистом). Такая технология называется Drag & Drop - перетаскивание (или перетащил и оставил).
Использование этой технологии, по-моему является роскошью, однако придает программе
профессиональный вид, а иногда даже делает интерфейс более удобным для пользователя.
Реализовать это довольно просто. Но прежде всего надо уяснить себе следующее:
Объект может быть взят только оттуда и перетащен только туда, как это определил
программист. Иными словами, для реализации этой технологии должен быть объект-источник
Drag и объект-приемник Drop и с каждым объектом, чтобы он поддерживал Drag&Drop,
необходимо поработать отдельно.
Для реализации этой технологии мы имеем небогатый выбор событий. Их всего два,
но этого вполне достаточно, чтобы внести неразбериху в твой проект, если в нем
уже имеются процедуры событий обработки мыши или клавиатуры. Поэтому, как мне
ни грустно говорить,тебе надо внимательно с ними ознакомиться.
Теперь можно начинать чего-нибудь потаскать. Начнем с малого, а именно с автоматического перетаскивания.
Автоматическое перетаскивание.
Автоматическое перетаскивание - наиболее простая и
наиболее худшая реализация технологии Drag&Drop.
Делается это элементарно. У многих объектов имеется свойство DragMode.
Оно определяет режим перетаскивания для объекта и может принимать два значения:
.DragMode=0 , т. e. вручную. и .DragMode=1 , т.е. автоматически.
По умолчанию оно в проекте всегда установлено состояние 0, то бишь ручное, и
это правильно. Но мы идем идиотским путем (а его нужно пройти обязательно),
поэтому установим свойство DragMode=1. Это можно сделать в окне свойств, а можно
программно.
Давайте создадим новый exe-прокт и посмотрим, как это все работает. Положим
на форму Text1, Text2 и Text3 со свойствами Multiline=True.
Сейчас мы попытаемся организовать перетаскивание содержимого Text1 и Tex2 в
Text3. И это нам удастся. Пишем код. Начнем со стандартного (хоть тут и нет
переменных)
Option
Explicit
В загрузке формы установим автоматический режим свойства DragMode для
Text1 и Text2 и заполним их текстом, а Text3 очистим:
Private Sub
Form_Load()
Text1.DragMode = 1
Text2.DragMode = 1
Text1.Text = "Это какой-то текст, записанный в Text1"
Text2.Text = "А это другой текст, записанный в Text2"
Text3.Text = ""
Да, чуть не забыл. Нам дана крутая возможность во время
перетаскивания менять изображение курсора мышки. Обалдеть можно. Хотя, на самом
деле, это важно. Пользователь должен контролировать состояние перетаскивания.
Ну и на этом спасибо. Курсор меняется с помощью свойства .DragIcon. Это
свойство определяет значок, который будет использоваться в качестве указателя
мыши при операции перетаскивания. Ты можешь в окне свойств установить свойству
DragIcon какую-нибудь иконку - файл с расширением .ico. Мы для ясности
сделаем это программно.
Text1.DragIcon = LoadPicture(App.Path & "\Move.ico")
Text2.DragIcon = LoadPicture(App.Path & "\Move.ico")
Но при программной загрузке картинок их всегда надо таскать с проектом, а при
загрузке картинок в окне свойств они становятся частью проектов и отдельно их
хранить не надо.
Все. Процедура Form_Load закончена.
End
Sub
Теперь логика следующая. Мы будем использовать для создания процедуры событие
DragDrop, а поскольку оно возникает по окончании процесса перетаскивания,
то процедуру надо создавать в Text3. Ведь именно там конечный пункт нашего
процесса.
Private Sub
Text3_DragDrop(Source As Control, X As
Single, Y As Single)
Координаты мыши X и Y нас сейчас мало интересуют, все равно VB сам определит,
перетащили мы объект на Text3 или нет. А вот аргумент Source мы используем.
С его помощью и ключевого слова TypeOf мы проведем проверку типа объекта
(то что мы перетаскиваем Text в Text, а не Text в Picture) и присобачив к нему
свойство .Text изменим содержимое Text3. Это и будет результат
перетаскивания.
If
TypeOf
Source Is TextBox Then
Text3.Text = Source.Text
End If
End Sub
Теперь ты можешь опробовать результат, запустив проект и поперетаскивать в Text3
и Text1 и Text2. Если ты не смог написать эти пятнадцать строк кода самостоятельно,
то скачать исходник примера можешь здесь.
Откровенно говоря в данном случае ключевое слово TypeOf притянуто за
уши, так как других объектов на форме нет.
Можно вместо этого проверять конкретно каждый элемент и присваивать
значение того, которого захотим. Для идентификации элемента есть простенькое
свойство Tag. Смысл его в том, что по нему с помощью аргумента Source
мы можем однозначно идентифицировать объект-источник. В отличие от других свойств,
значение свойства Tag не используется языком Visual Basic, но его можно
использовать для идентификации объектов. Этому свойству мы можем присвоить любое
имя-идентификатор, главное, чтоб они не были одинаковыми. Для этого в процедуру
Form_Load допишем две строчки:
Text1.Tag = "Text один"
Text2.Tag = "002"
Теперь наша процедура Text3_DragDrop будет выглядеть следующим образом:
Private Sub
Text3_DragDrop(Source
As Control, X As Single, Y As
Single)
If Source.Tag = "Text один"
Or Source.Tag = "002" Then
Text3.Text = Source.Text
End If
End Sub
Опять же, если чего не получилось, скачать эту фигню можно здесь.
Теперь рассмотрим результаты нашей деятельности. Юзер кайфует, радостно перетаскивая
текст из одного объекта в другой. Это несомненно хорошо. Потом юзеру надоедает
это делать и он с удивлением обнаруживает тот факт, что отредактировать-то текст
он не может ни в Text1, ни в Text2. Это несомненно плохо. А дело в том, что
инициируемые юзером события мыши или клавиатуры KeyDown, KeyPress,KeyUp, MouseDown,
MouseMove и MouseUp распознаваться НЕ БУДУТ!
Видя такое дело, нам целесообразно перейти к более сложному, но контролируему
делу - ручному перетаскиванию.
Метод
Drag - ручное перетаскивание.
Этот метод начинает, завершает или отменяет операцию перетаскивания любого
из элементов управления кроме Line, Menu, Shape, Timer и CommonDialog. Он позволит
нам не блокировать объект для редактирования, использовать всевозможные иконки,
чтоб юзер видел, что творит при перетаскивании и вообще правильный метод.
Еще раз напоминаю очень важную вещь, если ты не понял из предыдущего: результат
перетаскивания над перемещаемым объектом (копирование, удаление, вставка и т.д.)
определяется в объекте-приемнике в процедуре обработки события DragDrop.
Итак, для того, чтобы начать чего-нибудь перетаскивать, надо перейти в режим
перетаскивания. Для этого обычно используется процедура события MouseDown
для объекта-источника. В ней мы включаем метод Drag. Для включения-выключения
метода и отмены перетаскивания используются следующие константы, их объявлять
не надо:
vbCancel =0 'отменяет операцию перетаскивания
vbBeginDrag =1 'включает метод Drop
vbEndDrag =2 'выключает метод Drop
Давай-ка лучше сделаем новый exe-проект и попробуем все на практике. Наш новый
проект мало чем отличается от старого по внешнему виду, но не по коду. На форме
у нас будут Text1, Text2, Text3 и еще кнопка Command1. Смысл проекта в том,
чтобы перетаскивать содержимое Text1 в Text3, а Text2 запрещен для перетаскивания.
И для прикола, потаскаем по форме командную кнопку Command1. Итак, начнем.
Объявим переменную Flag как булеву. На фига я ее ввожу? Ну не знаю, чтобы позволить
юзеру беспрепятственно редактировать текст в объекте-источнике, т.е в Text1.
Т.е. изначально Flag=False и при первом щелчке метод Drag в процедуре Text1_MouseDown
не включается. Юзер спокойно может редактировать текст. Но в конце процедуры
Flag меняет свое значение на противоположный (Flag = Not Flag) и при повторном
нажатии кнопки мыши уже включается метод Drag.
Option Explicit
Dim Flag As Boolean
В процедуре загрузки формы зададим какое-нибудь содержимое TextBox'ам (можем
и не задавать и вообще наплевать на нее):
Private Sub
Form_Load()
Text1.Text = "Это какой-то текст, записанный в Text1"
Text2.Text = "А я вообще не знаю, что здесь делаю"
Text3.Text = "А это другой текст, записанный в Text3"
End Sub
Далее в событии MouseDown для объекта-источника Text1 включим
метод Drag для левой кнопки мыши. И меняем состояние переменной Flag:
Private Sub
Text1_MouseDown(Button
As Integer, Shift As Integer,
X As Single, Y As Single)
'проверяем, если нажата левая кнопка мыши и это повторное
нажатие то
If Button = vbLeftButton And
Flag = True Then
'включаем метод Drag
Text1.Drag vbBeginDrag
'загружаем общую иконку для курсора в виде молнии. Она
будет обозначать,
'что объект готов к перетаскиванию
Text1.DragIcon = LoadPicture(App.Path & "\Move.ico")
End If
'меняем значение флага на противоположное
Flag = Not Flag
End Sub
В объекте-приемнике по событию DragDrop производим результат перетаскивания,
т.е. присваиваем значение Text3=Text1. При этом проверяем тип объекта-источника:
Private Sub
Text3_DragDrop(Source
As Control, X As Single,
Y As Single)
'проверяем, соответствует ли тип объекта-источника TextBox'у
If TypeOf Source Is
TextBox Then
'если да, то
Text3.Text = Source.Text
'и для солидности передадим фокус в объект-приемник (Text3)
Text3.SetFocus
End If
End Sub
Поскольку наглядность перетаскивания для юзера чрезвычайно важна, загрузим иконки
в соответствии с положением мыши для объекта-источника (Text1):
Private Sub
Text1_DragOver(Source
As Control, X As Single, Y As
Single, State As Integer)
'если мышь над объектом-источником грузим обычную иконку
(молния)
If State = vbEnter Then
Text1.DragIcon = LoadPicture(App.Path & "\Move.ico")
'если покидает объект, то критический треугольник
ElseIf State = vbLeave Then
Text1.DragIcon = LoadPicture(App.Path & "\No.ico")
End If
End Sub
и для объекта-приемника. Причем, обратите внимание, что в процедуре Text3 объекта-приемника
мы определяем иконки для объекта-источника (Text1). В противном случае возникнет
путаница.
Private Sub
Text3_DragOver(Source
As Control, X As Single,
Y As Single, State As Integer)
'если мышь над объектом-приемником, то листик с кнопкой
- готовность принять объект
If State = vbEnter Then
Text1.DragIcon = LoadPicture(App.Path & "\Yes.ico")
'если вне объекта-приемника - то критический треугольник
ElseIf State = vbLeave Then
Text1.DragIcon = LoadPicture(App.Path & "\No.ico")
End If
End Sub
Вот вобщем-то и все. В заключении я хочу показать, что использование проверки
типа объекта-источника важна. На этой же форме включим метод Drag для командной
кнопки Command1.
Private Sub
Command1_MouseDown(Button
As Integer, Shift As Integer,
X As Single, Y As Single)
If Button = vbLeftButton Then
Command1.Drag vbBeginDrag
End If
End Sub
и напишем процедуру ее таскания по форме
Private
Sub
Form_DragDrop(Source As Control,
X As Single, Y As Single)
If TypeOf Source Is CommandButton
Then
Source.Move X, Y
End If
End Sub
Если бы мы не проверяли тип объекта с помощью ключевого слова TypeOf,
то при попытке перетащить кнопку в Text3 получили бы ошибку и фатальное завершение
программы. Можешь попробовать. А при наличии проверки наши методы не мешают
друг другу и все проходит успешно.
В этой главе мы разобрали технологию Drag&Drop для перетаскивания в пределах
одного нашего приложения. Скачать исходник примера можно вверху страницы.
В следующей главе мы попробуем исследовать эту технологию для обмена данных
между разными приложениями.
Copyright
© 2005 4us
|