Опубликован: 13.09.2006 | Уровень: для всех | Доступ: платный | ВУЗ: Тверской государственный университет
Лекция 14:

Проектирование интерфейса. Объекты диалоговых окон

Объект DataObject

Этот объект не элемент управления, но участвует в операциях перетаскивания выделенных текстов из одного элемента управления в другой. В нем одновременно могут храниться несколько текстовых данных в разных форматах. Когда в DataObject помещается новый текст с имеющимся там форматом, то прежний текст с этим форматом заменяется на новый.

Поведение DataObject похоже на поведение буфера обмена. Однако DataObject существует только в момент работы приложения и исчезает после ее завершения, а данные в буфере обмена при этом не теряются, DataObject может хранить только текстовые данные, а буфер обмена - и графические. С другой стороны, DataObject - настоящий OLE-объект и поддерживает в отличие от буфера обмена операции перетаскивания текста.

Текст заносится в DataObject методом SetText, а извлекается оттуда методом GetText:

объект. SetText (StoreData [, format])

и

Строка = объект. GetText ([format]),

где объект - объект-владелец метода, StoreData - текст, который надо запомнить в объекте, format - это необязательный параметр, задающий "формат" данных ( 1 соответствует стандартному текстовому формату, а другие числа и строки соответствуют пользовательским форматам). Если параметр format в вызове SetText явно не указан, то запоминаемому тексту присваивается формат стандартного текста 1. Так как для каждого формата DataObject содержит лишь один текст с этим форматом, то фактически формат играет роль ключа, по которому текст заносится и извлекается из DataObject. Метод GetFormat позволяет узнать, имеется ли в объекте DataObject текст определенного формата:

BooleanVar = объект. GetFormat (format)

Переменная BooleanVar получит значение True, если данные с указанным форматом входят в объект. Объект DataObject может обмениваться данными с буфером обмена посредством методов GetFromClipboard и PutInClipboard. Оператор:

String = объект. GetFromClipboard ()

помещает содержимое буфера обмена в DataObject, а вызов:

объект. PutInClipboard

переносит данные из DataObject, имеющие текстовый формат 1, в буфер обмена.

Допустим, в диалоговом окне имеются два поля ввода TextIn и TextOut, командная кнопка CmbCopy и метка Lable1. Занесем при инициализации окна в поле TextIn текстовую информацию и инициализируем глобальные переменные:

Public NewData As DataObject
Public NumClick As Integer

Private Sub UserForm_Initialize () 
	Set NewData = New DataObject		'инициализация объекта
	NumClick = 0				'число щелчков
	TextIn. Text = "Пример переноса данных с помощью DataObject "

End Sub

При последовательных щелчках командной кнопки занесем содержимое поля TextIn в объект DataObject методом SetText, из него перенесем в буфер обмена с помощью PutInClipboard, а уже из него поместим в поле TextOut методом Paste. О выполнении очередной операции будет сообщать метка Label1.

Private Sub CmdCopy_Click () 
	Select Case NumClick
		Case 0
			NewData. SetText TextIn. Text
			Label1. Caption = "Из TextIn в DataObject"
		Case 1
			NewData. PutInClipboard
			Label1. Caption = "Из DataObject в буфер обмена"
		Case 2
			TextOut. Paste
			Label1. Caption = "Из буфера обмена в TextOut"
	End Select
	
	NumClick = NumClick + 1
	If NumClick = 3 Then NumClick = 0

End Sub

Разумеется, перенос информации из одного поля в другое можно было осуществить и через буфер обмена, минуя DataObject. Для копирования данных из поля ввода в буфер обмена можно вызвать метод Copy. Более важный метод этого объекта, инициирующий операцию перетаскивания, - StartDrag рассмотрим подробнее.

Перемещение объектов. Как реализовать технику DragAndDrop

При организации интерфейса в диалоговых формах зачастую полезно предоставить пользователю возможность использовать технику DragAndDrop (Переместить и Опустить), когда некоторый объект захватывается мышью, перетаскивается к другому целевому объекту и при опускании изменяет свойства целевого объекта. Типичным примером является возможность перетаскивания элементов из одного списка в другой. Другим примером является перетаскивание писем и опускание их в почтовый ящик. Важным элементом этой техники является изменение внешнего вида курсора. Захват объекта происходит при подведении курсора к объекту и нажатии левой кнопки мыши, В этот момент курсор меняет свою внешнюю форму. Затем, когда происходит перемещение мыши, то в тех областях, где расположен целевой объект, курсор снова меняет форму, показывая, что цель достигнута. Если в этот момент, отпустить левую кнопку, то операция перемещения заканчивается успешно, отпускание кнопки мыши в других областях приводит к неуспеху. Объект DataObject и его метод StartDrag является частью этой технологии работы. Достаточно сложно понять суть этого метода, не разобравшись и в остальных частях этой технологии, в частности, в целом ряде событий, возникающих в процессе перетаскивания.

О событиях пойдет речь чуть далее, а начнем рассмотрение все-таки с метода StartDrag, который инициирует операцию перетаскивания объекта DataObject, хранящего перетаскиваемую информацию. Но прежде стоит рассмотреть пример, на котором весь этот процесс будет объясняться. Будем рассматривать диалоговое окно, имеющее два элемента ѕ список и окно ввода. Список будет содержать цвета, а текстовое окно ввода ѕ цвет, любимый пользователем. Пользователь имеет возможность выбрать любой из элементов списка и перетащить его в окно ввода. Когда пользователь захватывает выбранный им элемент списка, то возникает некоторое событие. В нашем примере это событие MouseMove, обработчик которого и будет вызывать метод StartDrag объекта DataObject, хранящего значение перетаскиваемого элемента. Теперь, когда, хотя бы частично, прояснена ситуация, предшествующая вызову метода, рассмотрим его синтаксис:

Function StartDrag ([Effect As fmDropEffect])  As fmDropEffect

Эта функция обычно вызывается в операторе присваивания вида:

ResultEffect=объект. StartDrag ([Effect as fmDropEffect])

Необязательный параметр Effect и результат выполнения функции принадлежат перечислению fmDropEffect. Константы, входящие в это перечисление имеют следующие значения:

  • fmDropEffectNone = 0 - не копировать и не передвигать опущенный исходный элемент на место назначения,
  • fmDropEffectCopy = 1 - копировать опущенный исходный элемент на место назначения,
  • fmDropEffectMove = 2 - передвинуть опущенный исходный элемент на место назначения,
  • fmDropEffectCopyOrMove = 3 - скопировать или передвинуть опущенный исходный элемент на место назначения.

Параметр Effect задает цель операции и имеет по умолчанию значение 1 ( fmDropEffectCopy ). Обычно он опускается, поскольку значение по умолчанию задает наиболее вероятную цель операции. Возвращаемое методом StartDrag значение определяет результат выполнения операции. Его можно использовать для анализа того, что же произошло в результате перетаскивания на самом деле. Важно только понимать, что между запуском метода StartDrag в правой части оператора присваивания и присваиванием результата левой части переменной ResultEffect происходит много событий в процессе перемещения объекта, работают обработчики этих событий и результат говорит о том, как закончился этот процесс.

Вот как выглядит спроектированное нами диалоговое окно "Поле и Список" в процессе работы с ним:

Окно "Поле и Список" в процессе работы

Рис. 13. 6. Окно "Поле и Список" в процессе работы

В этом диалоговом окне пользователь имеет возможность выбрать произвольный элемент списка "Цвета" и перетащить его мышью в поле "Любимый цвет"

Рассмотрим обработчики событий, поддерживающие процесс перетаскивания. Начнем с обработчика события Initialize для диалогового окна, обеспечивающего инициализацию начального состояния:

Private Sub UserForm_Initialize () 
	With Me. DraggedList
		. AddItem "Красный"
		. AddItem "Оранжевый"
		. AddItem "Желтый"
		. AddItem "Зеленый"
		. AddItem "Голубой"
		. AddItem "Синий"
		. AddItem "Фиолетовый"
		. AddItem "Черный"
		. AddItem "Белый"

	End With
End Sub

Здесь инициализируется список "Цвета", имеющий имя DraggedList. Когда пользователь, выбирая элемент этого списка, нажимает левую клавишу мыши, готовясь перетащить этот элемент в другое место, у списка возникает событие MouseMove, обработчик которого имеет много параметров. Описание этого события, всех его параметров, описание других используемых нами событий, будут даны в последующих параграфах, а сейчас приведем текст этого обработчика:

Private Sub DraggedList_MouseMove (ByVal Button As Integer,  ByVal Shift As Integer,  _
					ByVal X As Single,  ByVal Y As Single) 
	Dim MyDataObject As DataObject
	Dim Msg As String
	Msg = "Видимо,  Вы уронили цвет при перетаскивании.  Повторите операцию!"
	If Button = 1 Then
		Debug. Print "MouseMove"
		Set MyDataObject = New DataObject
		Dim Effect As Integer
		MyDataObject. SetText DraggedList. Value
		Effect = MyDataObject. StartDrag (fmDropEffectCopy) 
		If Effect = 0 Then MsgBox  (Msg) 
		Debug. Print "Effect = ",  Effect
	End If

End Sub

О параметрах, как уже говорилось речь пойдет впереди, а сейчас прокомментируем его работу. Если в момент возникновения события нажата левая кнопка мыши, то создается новый объект DataObject, его метод SetText копирует значение выбранного элемента списка, а метод StartDrug запускает процесс перетаскивания. Заметьте, что метод StartDrug можно было бы вызывать без параметра, ѕ на результат это не повлияло бы. Результат перетаскивания анализируется и, если он закончился неуспехом ( Effect = 0 ), то выдается уведомляющее сообщение. Исполняемые операторы окаймлены отладочной печатью, что позволит нам продемонстрировать, что между первой печатью, уведомляющей о начале работы обработчика MouseMove, и последней печатью, уведомляющей о результате работы, будут напечатаны сообщения других обработчиков, к рассмотрению которых мы и переходим.

Событие BeforeDragOver возникает для объекта TextIn (поле ввода "Любимый цвет"), когда курсор в процессе перетаскивания попадает в область, занятую объектом. Заметьте, событие возникает многократно, поскольку курсор находится в этой области некоторое время. Вот текст обработчика этого события:

Private Sub TextIn_BeforeDragOver (ByVal Cancel As MSForms. ReturnBoolean,  _
		ByVal Data As MSForms. DataObject,  ByVal X As Single,  _
		ByVal Y As Single,  ByVal DragState As MSForms. fmDragState,  _
		ByVal Effect As MSForms. ReturnEffect,  ByVal Shift As Integer) 
	
	Cancel = True
	Effect = fmDropEffectCopy
	Debug. Print "DragOver"
End Sub

Заметьте, основное, что делает этот обработчик, он устанавливает значение параметра Effect. Поскольку эффект совпадает с целевым эффектом, то курсор в области, занятой полем TextIn, будет менять свою форму, принимая вид прямоугольника со знаком "+", указывающим, что цель достигнута и можно отпустить левую клавишу мыши. Завершающий оператор отладочной печати позволит проследить за числом вызовов этого обработчика.

Следующее событие для объекта TextIn возникает, когда отпущена левая клавиша мыши в области этого объекта. Вот его обработчик:

Private Sub TextIn_BeforeDropOrPaste (ByVal Cancel As MSForms. ReturnBoolean,  _
	ByVal Action As MSForms. fmAction,  ByVal Data As MSForms. DataObject,  _
	ByVal X As Single,  ByVal Y As Single,  ByVal Effect As MSForms. ReturnEffect,  _
	ByVal Shift As Integer) 
	
	Cancel = True
	Effect = fmDropEffectCopy
	TextIn. Text = Data. GetText
	Debug. Print "DragPaste"
End Sub

Здесь также возвращается значение эффекта. Главное, завершается операция перетаскивания копированием текста в поле ввода из переданного в качестве параметра объекта Data класса DataObject, хранящего значение цвета, выбранного пользователем.

Совместная работа этих трех обработчиков событий и вызываемые в них методы объекта DataObject - SetText, GetText, StartDrag - обеспечивают в совокупности технику DragAndDrop. В заключение о двух экспериментах при работе с диалоговым окном. Вначале, мы не донесли выбранный нами цвет до окна ввода, отпустив левую клавишу мыши на дороге к нему. Вот как выглядело сообщение, полученное нами:

Сообщение о потере объекта при перетаскивании

Рис. 13.7. Сообщение о потере объекта при перетаскивании

Затем повторно выбранный нами зеленый цвет был успешно перетащен в окно "Любимый цвет". Приведем отладочную печать этих двух экспериментов:

MouseMove
Effect = 0 
MouseMove
DragOver
DragOver
DragOver
DragPaste
Effect = 1

Первые две строчки связаны с неудачной попыткой переноса, когда эффект был нулевым. Следующие строки описывают успешный эксперимент. Заметьте, что между печатью, информирующей о начале работы обработчика MouseMove и его заключительной печатью об успешном эффекте, вклинились сообщения, поступающие от обработчиков событий DragOver и DropOrPaste. Заметьте, я оставил только три сообщения от обработчика DragOver, реально их было 25. На этом описание примера заканчивается, но разговор о событиях еще предстоит.

полина есенкова
полина есенкова
Дмитрий Вологжин
Дмитрий Вологжин
Добрый день, прошел тесты с 1 по 9, 10 не сдал, стал читать лекцию и всё пройденные тесты с 1 по 9 сбросились, когда захотел пересдать 10 тест.
Людмила Слесарева
Людмила Слесарева
Россия
Александр Орлов
Александр Орлов
Россия