Прием перетаскиваемых объектов
События, возникающие в процессе перемещения объектов, перечислены ниже в том порядке в каком они возникают.
OnStartDrag (тип TStartDragEvent) - в начале выполнения операции генерируется объектом-источником. Параметры, которые передаются обработчику событий: объект приемник DragObject (тип TDragObject), объект-источник Source (тип TObject).
OnDragOver (тип TDragOverEvent) - создает объект-приемник, когда над ним оказывается перемещаемый объект. Параметры, которые передаются обработчику событий: объект-приемник Sender (тип TObject), объект-источник Source (тип TObject), состояние перемещения State (тип TDragState), X и Y (тип integer) - текущие координаты указателя мыши, Accept (тип boolean) признак подтверждения операции перемещения. Состояние перемещения дает понять находиться ли перемещаемый объект в области приемника, передвигается ли в ней, покинул ее. Переданные параметры дают возможность объекту-приемнику принять или отклонить объект-источник. Параметр Accept устанавливается в значение true если операция перемещения принята, в противном случае - false.
onDragDrop (тип TDragDropEvent) - создается объектом-приемником, когда перемещаемый объект опускается на нем. Обработчику события передаются текущие координаты указателя мыши, объект приемник Sender (тип TObject), исходный объект перемещения Source (тип TObject).
onEndDrag (тип EndDragEvent) - создается при завершении операции перетаскивания. Передаются обработчику события координаты X и Y точки, где оказался объект-источник Sender и объект приемник Target.
Для создания перетаскивания достаточно реализовать два события: OnDragDrop и OnDragOver при установленном свойстве DragMode равном dmAutomatic. В противном случае начало операции перемещения, метод BeginDrag, необходимо программисту закодировать.
Для закрепления материала создадим следующее приложение. На форму поместим компонент Panel. В свойстве DragMode Инспектора Объектов установим значение dmAutomatic. Выделим объект форма и с помощью Инспектора Объектов создадим нижеследующие события:
__fasvcall FormDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
{
if (Source = Panel1)
Accept=True;
else
Accept=False;
}
__fasvcall TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer);
{
Panel1‒>Left=X;
Panel1‒>Top=Y;
}
Теперь запустив приложение и нажав над панелью кнопку мыши мы можем перемещать объект панель по всей форме.
Задание 1
На пользовательской форме должны быть расположены 3 списка. Один из списков содержит названия напитков. Пользователь может переносить элементы из этого списка в списки «Любимые» и «Нелюбимые» и обратно. При этом перемещаемый элемент должен удалятся из списка-источника. То есть, например, перенос элемента «Чай» из общего списка в список «Любимые» происходит в следующем порядке: он добавляется в список «Любимые» и удаляется из общего списка. Таким образом общее количество элементов всех трех списков остается постоянным. Перенос элементов между списками должен осуществляться по нажатию на соответствующие кнопки, либо мышью (система Drag and Drop).
Списки «Любимые» и «Нелюбимые» должны сохраняться в текстовые файлы.
Для создания формы использовать компоненты:
Label – для подписей
ListBox – для вывода списков
Button – для инициирования действий
Рекомендуемая компоновка формы программы представлена на рисунке 1.
Рис. 1 Рекомендуемая компоновка формы
6. На панели компонентов выбрать вкладку Standard, расположить на форме компоненты Label , Button и ListBox в требуемом количестве (см. рис.1).
7. Изменить подписи объектов Label и пользовательской формы Form1. Для этого необходимо у перечисленных объектов отредактировать свойство Caption в соответствии с рисунком 1.
8. Для заполнения ListBox2 названиями напитков необходимо выделить этот список, щелкнув по нему левой кнопкой мыши, и в окне Object Inspector найти поле свойства Items. При нажатии в этом поле на кнопку с тремя точками появится окно String List Editor, в котором следует перечислить названия всех напитков (см. рис. 2).
Рис. 2. Редактирование свойства Items в окне String List Editor
9. Перенос элементов между списками с помощью мыши можно организовать следующим образом.
a. Для каждого списка задать свойству DragMode значение dmAutomatic.
b. Для списка ListBox3 назначить обработчик событие OnDragOver. Для этого нужно выбрать список ListBox3 и в окне Object Inspector на вкладке Events найти событие OnDragOver и дважды щелкнуть по его полю.
При этом автоматически будет создана заготовка для функции-обработчика. В тело этой функции следует записать следующий код:
void __fastcall Tform1::ListBox3DragOver(TObject *Sender, TObject *Source, int X, int Y, TDragState state, bool &Accept)
}
/*функция-обработчик события OnDragOver. Если данная функция у объекта не задана, то такой объект не способен воспринимать перетаскиваемые в него объекты.
Создаем указатель на объект-источник Source, который будет восприниматься как ListBox. Например при перетаскивании из списка ListBox2 в список ListBox1, источником являеься список ListBox2 */
TListBox *Sour=(TListBox *) Source;
/*если у объекта-источника общее количество элементов (строк) больше 0 и выбран элемент, то его перенос разрешается. Иначе запрещается*/
if(Source−>Coumt > 0 && Source−>ItemIndex > -1)
accept=true;
else
accept=false;
}
c. Для этого же списка ListBox3 назначить обработчик событие OnDragDrop. Для этого нужно создать заготовку функции-обработчика события OnDragDrop и в нее записать ниже приведенный код:
void __fastcall TForm:: ListBox3DragDrop(TObject *Sender, TObject *Source, int X, int Y)
{
/*Функция-обработчик события OnDragDrop описывает действия при подтверждении (в момент, когда отпускается кнопка мыши) перетаскивания элемента из одного списка в другой создаем указатель на объект-источник Source, который будет восприниматься как listBox. Например, при перетаскивании из списка ListBox2 в список ListBox1, источником является список ListBox2*/
TListBox *Sour=(TListBox *)Source;
/*Создаем указатель на объет-приемник Sender, который будет воспиниматься как ListBox. Например, при перетаскивании из списка ListBox2 в список ListBox1, приемником является список ListBox1*/
TListBox *Send=(TListBox *)Sender;
/* Объявляем переменную для определения координат мыши*/
TPoint p;
/* Объявляем переменную для определения элемента списка, на который указывает курсор мыши */
int I;
/* Определяем положение курсора мыши*/
p=Point(X,Y);
/* Определяем индекс в списке-приемника, на который указывает курсор мыши*/
I=Send−>ItemAPos(p,true);
/* Вставляем элемент в список-приемник, перетащенный из списка-источника. Положение перетащенного элемента будет определено положением курсора мыши*/
Send−>Items−>Delete(Sour−>ItemIndex);
/* Удаляем из списка-источника перетащенный элемент*/
}
d. Для списков ListBox2 и ListBox1 в обработчиках событий OnDragOver и OnDragDrop выбрать из выпадающих списков уже готовые функции ListBox3DragOver и ListBox3DragDrop:
10. Сохранить проект.
11. Провести отладку и тестирование программы.
Контрольные вопросы
- Опишите технологию Drag & Drop?
- События, возникающие в процессе перемещения объектов?
- Параметры, которые передаются обработчику событий объекту-приемнику и обекту-источнику?
- Когда возникает событие OnStartDrag?
- Когда возникает событие OnDragOver?
- Когда объектом-приемником создается событие onDragDrop?
- Когда происходит событие onEndDrag?
- Когда значение параметра Accept устанавливается в true, а когда в false?