Главная страница
Случайная страница
КАТЕГОРИИ:
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
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 для перетаскивания в пределах одного нашего приложения. Скачать исходник примера можно вверху страницы. В следующей главе мы попробуем исследовать эту технологию для обмена данных между разными приложениями.
Итак, в прошлой главе мы проанализировали технологию Drag& Drop при перетаскивании под управлением событий. Это хорошо при работе внутри нашего проекта. Если же нам необходимо осуществить перетаскивание из окна совсем другого приложения, то навряд-ли мы дождемся наступления какого-нибудь события для нашей формы (или ее объектов), если будем щелкать по чужому окну. Поэтому сейчас мы проанализируем перетаскивание с помощью OLE технологий. Принцип перетаскивания здесь тот же, что и при перетаскивании с использованием событий - есть объект-приемник и объект-источник. Один и тот же объект может быть и приемником и источником (в случае если он используется и для приема и для передачи). Как и в прошлой главе, начнем с чего попроще - с автоматического перетаскивания.
Автоматическое перетаскивание.
| Очень простая и удобная технология. С его помощью мы просто перемещаем содержимое одного объекта в другой объект. Для включения автоматического перетаскивания мы имеем два свойства:
.OLEDropMode - активизирует объект в качестве приемника
|
| может принимать значения:
|
| 0 (vbOLEDropNone) - Нет
|
| 1 (vbOLEDropManual) - Вручную
|
| 2(vbOLEDropAutomatic) - Авто
| .OLEDragMode - активизирует объект в качестве передатчика
|
| может принимать значения:
|
| 0 (vbOLEDragManual) - Вручную
|
| 1 (vbOLEDragAutomatic) - Авто
| Эти свойства можно задавать как в окне свойств, так и программно, в ходе выполнения программы.
Но, к сожалению, не все элементы управления (объекты) поддерживают автоматическое перетаскивание. Некоторые элементы поддерживают оба свойства - и .OLEDropMode и .OLEDragMode, а некоторые - только OLEDragMode. А ряд элементов вообще нельзя использовать для автоматического перетаскивания. Вот элементы и поддерживаемые ими свойства.
Элемент управления с режимом авто (OLE перетаскивание)
| .OLEDropMode
| OLEDragMode
| ComboBox
| НЕТ
| ДА
| DBComboBox
| НЕТ
| ДА
| DBGrid
| ДА
| ДА
| DBListBox
| НЕТ
| ДА
| DirecoryListBox
| НЕТ
| ДА
| FileListBox
| НЕТ
| ДА
| Image
| ДА
| ДА
| ListBox
| НЕТ
| ДА
| ListView
| НЕТ
| ДА
| MaskedEdit
| ДА
| ДА
| PictureBox
| ДА
| ДА
| RichTextBox
| ДА
| ДА
| TextBox
| ДА
| ДА
| TreeView
| НЕТ
| ДА
| Создадим новый exe-проект. Положим на форму PictureBox1 и Image1. Установим программно свойства перетаскивания в автоматический режим:
Private Sub Form_Load() Picture1.OLEDropMode = vbOLEDropAutomatic 'автоматический прием Picture1.OLEDragMode = vbOLEDragAutomatic 'автоматическая передача Image1.OLEDropMode = vbOLEDropAutomatic Image1.OLEDragMode = vbOLEDragAutomatic End Sub
Это, собственно, все. Запустим проект. Если теперь мы откроем какую-нибудь картинку в приложении, поддерживающем технологию OLE-перетаскивания (например Photoshop, но при этом должен быть включен инструмент " Двигать" (" Move")), то запросто можем перетащить картинку из него в наш проект и обратно. Также можно перетаскивать и внутри нашего проекта из Picture1 в Image1 и наоборот. При этом обратите внимание на то, что при перетаскивании нажатой кнопкой мыши картинка в объекте-передатчике уничтожается, т.е. происходит перемещение. Чтобы происходило копирование (картинка сохранялась) перетаскивание надо осуществлять с нажатой кнопкой Ctrl. При автоматической реализации OLE-технологии Drag& Drop мы не обрабатываем результаты перетаскивания. Картинка (или другие данные) должны быть загружены в объект-передатчик. Т.е. мы не можем, например, перетащить в Image1 иконку графического файла.jpg из проводника Windows в надежде, что этот файл там неожиданно откроется. Поскольку мы программно этого не описали, никаких сюрпризов ждать не приходится. Для более гибкого (и соответственно более сложного) управления перетаскиванием можно попробовать ручное перетаскивание.
Метод OLEDrag - ручное перетаскивание.
| Ручное управление перетаскиванием позволяет программировать различные дополнительные действия. Кроме того с его помощью можно работать с такими элементами управления, не поддерживающими автоматическое перетаскивание, как CommandButton, Label, CheckBox, OptionButton, Frame и DriveListBox.
Итак, приступим. Помимо рассмотренных нами уже свойств .OLEDropMode и .OLEDragMode мы имеем еще целый ряд событий и их нам, как говорится, надо:
| Private Sub объект_OLEDragDrop(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single)
| Возникает при перетаскивании объекта-источника в объект-приемник. data - объектDataObject содержит форматы (и возможно данные для этих форматов), которые обеспечивает источник. Если в объекте никаких данных не содержится, то они предоставляются при вызове метода GetData. Методы SetData и Clear использованы быть не могут. effect - число long, устанавливаемое приемником, для опознавания действия, которое выполнено (например удалять или копировать содержимое источника). Может принимать значения следующих констант: 0 (vbDropEffectNone) - приемник не может принять данные 1 (vbDropEffectCopy) - передача копии (исходник источника сохраняется) 2 (vbDropEffectMove) - перемещение данных (исходник источника удаляется) button - соответствует состоянию кнопки мыши. 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 объект_OLEDragOver(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single, state As Integer)
| Возникает при перетаскивании одного компонента над другим. data - объектDataObject содержит форматы (и возможно данные для этих форматов), которые обеспечивает источник. Если в объекте никаких данных не содержится, то они предоставляются при вызове метода GetData. Методы SetData и Clear использованы быть не могут. effect - число long, устанавливаемое приемником, для опознавания действия, которое выполнено (например удалять или копировать содержимое источника). Может принимать значения следующих констант: 0 (vbDropEffectNone) - приемник не может принять данные 1 (vbDropEffectCopy) - передача копии (исходник источника сохраняется) 2 (vbDropEffectMove) - перемещение данных (исходник источника удаляется) -2147483648 (& H80000000) (VbDropEffectScroll) - происходит или подготавливается прокрутка в приемнике (только при выполнении пользовательской прокрутки в приемнике). button - соответствует состоянию кнопки мыши. 1 - левая кнопка, 2 - правая и 4 - средняя. shift - указывает состояние кнопок shift, alt и ctrl (1- shift, 2- alt и 4 - ctrl). При удержании больше одной кнопки их значения складываются (ctrl-alt = 4+2=6). Значения переменных x и y возвращают текущие координаты курсора мыши (x - по-горизонтали, y - по-вертикали) в единицах измерения, заданных свойствами ScaleHeight, ScaleWidth. state - показывает состояние перетаскиваемого объекта по отношению к форме. Может принимать следующие значения: 0 (vbEnter) - источник в пределах приемника 1 (vbLeave) - источник вне окрестности приемника 2 (vbOver) - источник перемещается в приемнике из одного положения в другое
|
| Private Sub объект_OLEGiveFeedback (effect As Long, defaultcursors As Boolean)
| Происходит после каждого события _OLEDragOver. Позволяет показывать пользователю (например с помощью изменения курсора мыши) ход перетаскивания. effect - число long, устанавливаемое в событии _OLEDragOver, и определяет действие, которое может быть педпринято, если пользователь опускает объект на компонент. Используется для визуализации перетаскивания. Может принимать значения следующих констант: 0 (vbDropEffectNone) - приемник не может принять данные 1 (vbDropEffectCopy) - передача копии (исходник источника сохраняется) 2 (vbDropEffectMove) - перемещение данных (исходник источника удаляется) -2147483648 (& H80000000) (VbDropEffectScroll) - происходит или подготавливается прокрутка в приемнике (только при выполнении пользовательской прокрутки в приемнике). defaultcursors - значение True, если использовать курсор мыши по умолчанию и False, если не использовать. (Курсор может быть установлен свойством.MousePointer объекта Screen)
|
| Private Sub объект_OLEStartDrag (data As DataObject, a llowedeffects As Long)
| Происходит, когда выполняется метод OLEDrag или когда объект инициирует операцию перемещения, если свойство OLEDragMode установлено в значение 1 - авто. data - объектDataObject содержит форматы (и возможно данные для этих форматов), которые обеспечивает источник. Если в объекте никаких данных не содержится, то они предоставляются при вызове метода GetData. Методы SetData и Clear использованы быть не могут. allowedeffect - число long, содержит результаты, поддерживаемые приемником. Значения данного параметра устанавливаются программистом. Может принимать значения следующих констант: 0 (vbDropEffectNone) - приемник не может принять данные 1 (vbDropEffectCopy) - передача копии (источник сохраняется) 2 (vbDropEffectMove) - перемещение данных (источник удаляется)
|
| Private Sub объект_OLESetData(data As DataObject, dataformat As Integer)
| Происходит на источнике, когда приемник выполняет метод GetData на объекте DataObject, но данные указанного формата еще не загружены. data - объектDataObject, в который необходимо поместить запрашиваемые данные. Компонент вызывает метод SetData, чтобы загрузить запрашиваемый формат. dataformat - целое число, уточняющее формат данных. Используется для указания источнику, что загружать в объект DataObject.
|
| Private Sub объект_OLECompleteDrag ([ effec t As Long])
| Возникает, когда источник опускается на получатель, информируя источник, что операция перетаскивания выполнена или отменена. effect - число long, устанавливаемое источником, позволяющее определить действие, которое выполнено. Может принимать значения следующих констант: 0 (vbDropEffectNone) - приемник не может принять данные 1 (vbDropEffectCopy) - передача копии (источник сохраняется) 2 (vbDropEffectMove) - перемещение данных (источник удаляется)
|
| Прочитав этот полубезумный бред, мы не будем впадать в истерику. Нам известна аксиома - " Visual Basic - это не просто просто, а очень просто". Исходя из этой аксиомы, морща лоб от напряжения и пуская слюни от усердия, мы попытаемся сейчас реализовать технологию перетаскивания на раз-два-готово. Изначально будем считать, что у нас есть наше приложение и некое чужое. Вот между ними мы и будем таскать объекты, как китайские кули.
Итак, указаные выше события возникают каждое на своем объекте:
на стороне объекта-источника
| на стороне объекта-приемника
| OLEStartDrop
| OLEDragDrop
| OLESetData
| OLEDragOver
| OLEGetFeedback
|
| OLECompleteDrag
|
| Вроде как на стороне приемника их меньше, вот и начнем с конца. Создадим новый exe-проект и положим на него Picture1 и Text1. В них мы должны перетащить картинку и текст соответственно из неких сторонних приложений. Таким образом, на нашем проекте имеется только объекты-приемники, а формирование на стороне объекта-источника мы оставим на совести чужого приложения. Сперва мы должны инициализировать наши Picture1 и Text1 как объекты-приемники. Для этого мы используем то же свойство .OLEDropMode, что и при автоматическом перетаскивании, только значение его должно быть в этот раз vbOLEDropManual, т.е. ручное. Сделаем это в процедуре загрузки формы (хотя можно и в окне свойств проекта):
Private Sub Form_Load() Picture1.OLEDropMode = vbOLEDropManual Text1.OLEDropMode = vbOLEDropManual End Sub
Зная, что при окончании перетаскивания на стороне приемника возникает событие _OLEDragDrop, используем его для загрузки картинки в Picture1. Но как же нам передать в нашу процедуру, что за картинка у нас, собственно, перетаскивается? А данные об этом хранятся в объекте DataObject. Прежде всего, этот объект позволяет нам проверить, того ли формата данные мы пытаемся загрузить в приемник (Picture1), так как, например, текст в PictureBox загружать не очень хорошо. Для этого объект DataObject имеет метод GetFormat. Его синтаксис следующий:
|