Главная страница
Случайная страница
КАТЕГОРИИ:
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
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. Его синтаксис следующий:
|