Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы Delphi / Лабораторная работа 9

.doc
Скачиваний:
30
Добавлен:
17.04.2015
Размер:
76.8 Кб
Скачать

Лабораторная работа № 9. Drag & Drop

Упражнение 1. Пусть имеется 8 коробочек и 8 фигур. Фигуры отличаются друг от друга формой (круг или квадрат), цветом (белый или чёрный) и размером (большой или маленький). Каждая коробочка может содержать фигуру только определённого типа (форма, размер, цвет). Напишите приложения для размещения фигур в коробочки.

Решение

Создайте новый проект. Сохраните новое приложение в папке Drag&Drop_1 – файл модуля под именем Main.pas, файл проекта – DragDrop_1.dpr.

1 этап. Визуальное проектирование

Для реализации данной игры воспользуемся 8 компонентами типа TShape (это будут фигуры) и 8 компонентами типа TLabel (это коробочки).

Рис. 1

Установите значения свойств формы следующим образом:

Name

Drag_Dropfrm

Caption

Drag&Drop

Для именования компонент введем следующие обозначения: по размеру – B (big, большой) или S (small, маленький), по цвету – В (black, черный) или W (white, белый), по форме – S (square, квадрат) или C (circle, круг). У компонентов типа TShape добавим окончание shp. Таким образом, имя компонента, изображающего большой чёрный квадрат, будет BBSshp. А у белого маленького круга – SWCshp. Используя эти обозначения, измените свойства Name компонентов Shape.

Компоненты класса Tlabel назовём по такой же схеме, изменим только окончание на lbl. То есть, если коробочка предназначена для большого чёрного круга, то название будет BBClbl. Измените свойства Name компонентов Label в соответствии с введенной схемой обозначения.

У всех компонентов Label установите свойств AutoSize в значение False, Transparent – True (чтобы компоненты, помещенные на них были видны), значения свойств Caption в соответствии с рис. 1.

Свойство DragMode компонентов Shape установите в значение dmAutomatic.

Для проверки правильности выбора коробочки (компонента типа TLabel) для компонента типа TShape, воспользуемся свойством Hint. Значения свойства Hint задайте в соответствии с названием компонента, но без окончания (shp или lbl). Например, у компонента SWSshp оно будет равно SWS, при чём оно будет совпадать со значением свойства для компонента SWSlbl.

2 этап. Создание программного кода

Создайте обработчик события OnDragOver для компонента BWSlbl. Чтобы определить, можно ли положить фигуру в коробочку, необходимо сравнить значения свойства Hint перетаскиваемого объекта и объекта – приёмника. Если эти значения равны, то коробочка подходит, и соответственно Accept должно быть равно True, иначе объект сбросить нельзя и Accept = False

procedure TDrag_Dropfrm.BWSlblDragOver(Sender, Source: TObject;

X,Y: Integer; State: TDragState; var Accept: Boolean);

Begin

if (Sender is TLabel) and (Source is TShape) then

Accept:=((Sender as TLabel).Hint=(Source as TShape).Hint);

end;

Для остальных компонентов Label необходимо создать аналогичные обработчики события OnDragOver: в инспекторе объектов для всех компонентов Label в событии OnDragOver создайте ссылку на обработчик события TDrag_Dropfrm.BWSLblDragOver.

Примечание:

Если необходимо, чтобы при обработке события OnDragOver происходили какие-либо изменения с перетаскиваемым объектом, то желательно проверять его принадлежность к классу (операция is). Иначе могут возникнуть ошибки из-за несоответствия типов.

Сохраните проект. Запустите проект и убедитесь, что при перетаскивании фигур только над коробочкой, соответствующей фигуре, курсор имеет форму стрелки с прямоугольником, а во всех остальных случаях - стрелки с перечеркнутым кругом.

Если в обработчике события OnDragOver значение параметра Accept было равно true и вы попытались «сбросить» объект, то возникает событие OnDragDrop у компонента, на который объект был «сброшен». Заголовок обработчика этого события имеет вид:

procedure TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer);

Значения параметров данного события совпадают со значениями одноимённых параметров события OnDragOver.

В обработчике события OnDragDrop необходимо выполнить все действия над перетаскиваемым объектом по «сбрасыванию».

Вернемся к разрабатываемому приложению. Итак, если фигуру можно положить в коробочку, и вы отпускаете в этот момент клавишу мыши, то произойдёт событие OnDragDrop. Создайте обработчик события TDrag_Dropfrm.BWSLblDragDrop. В нём нужно изменить местоположение фигуры – пусть она будет находиться в коробочке. Для этого придётся лишь задать новые значения свойства Left и Top у перетаскиваемого компонента. Они будут зависеть от значений соответствующих свойств компонента – приёмника.

procedure TDrag_Dropfrm.BWSlblDragDrop(Sender, Source: TObject;

X, Y: Integer);

Begin

if (Source is TShape) then

with (Source as TShape ) do begin

{определяем абсолютные координаты перетаскиваемого компонента}

Left :=(Sender as TLabel ).Left+X;

Top :=( Sender as TLabel ).Top+Y;

end;

end;

Для остальных компонентов класса Tlabel установите ссылки на обработчик данного события.

Сохраните проект. Запустите проект и убедитесь, что в результате операции Drag&Drop фигура «сбрасывается» внутрь коробочки (т.е. соответствующего компонента Label).

При завершении перетаскивания (вне зависимости от того, приняты данные или нет) для перетаскиваемого объекта возникает событие OnDragEnd. Оно происходит также при отмене перетаскивания. Событие не является обязательным для выполнения. Операция перетаскивания может быть произведена и без обработки этого события. Не все компоненты генерируют данное событие

Заголовок обработчика события имеет вид:

procedure TForm1.<имя_компонента>EndDrag(Sender, Target: TObject;

X, Y: Integer);

Параметр Sender получает информацию о перетаскиваемом объекте. Параметр Target содержит информацию об объекте, который получил данные. Если перетаскиваемый объект не был принят, то Target= Nil объект. X , Y - координаты указателя мыши в момент отпускания левой кнопки.

В нашем приложении создайте обработчик события TDrag_Dropfrm.BWSshpEndDrag. В нём при удачном перемещёнии фигуры будем менять заголовок компонента-приёмника:

procedure TDrag_Dropfrm.BWSshpEndDrag(Sender, Target: TObject;

X, Y: Integer);

begin

if Target <> nil then (Target as Tlabel).Caption :=''

end;

Для всех остальных компонентов типа Tshape сделайте ссылки на обработчик данного события.

Сохраните проект. Убедитесь, что после «сбрасывания» фигуры надпись в соответствующем компоненте Label исчезает.

В начале операции перетаскивания происходит событие OnStarDrag.Событие возникает у перетаскиваемого объекта. Как и предыдущее событие, оно не является обязательным. Не все компоненты генерируют данное событие. Заголовок обработчика события имеет вид:

procedure TForm1.<имя_компонента>StartDrag(Sender: TObject;

var DragObject: TDragObject);

Параметр Sender содержит информацию о перетаскиваемом объекте. В параметре DragObject процедура получает информацию об объекте, создаваемом данным событием. Этот параметр используется для того, чтобы определить вид курсора или вид рисунка при перетаскивании объекта.

Методы

Существует несколько методов, относящихся к операции Drag&Drop. Но рассмотрим только один из них (BeginDrag), так как остальные применяются в основном при создании новых компонентов или для переопределения свойств у уже существующих.

Метод BeginDrag применяется для того, чтобы начать операцию перетаскивания. Метод понадобится только если свойство DragMode перетаскиваемого объекта установлено в значение dmManual.

Чтобы перетаскивание началось необходимо инициализировать метод BeginDrag у объекта, который надо перетащить. Удобнее всего это делать при обработке событий мыши данного объекта. Метод описан следующим образом: BeginDrag(Immediate: Boolean).

Единственный аргумент метода (Immediate:boolean) может принимать два значения. Если он равен True,то перетаскивание начинается немедленно. Если равен False,то перетаскивание начинается при смещении курсора мыши на 5 пикселей в любом направлении. Как правило, удобнее присваивать Immediate значение False, т.к. в этом случае можно обрабатывать нажатие кнопки мыши, не начиная операцию перетаскивания.

После применения метода с объектами будут происходить все те же события, что и при DragMode=dmAutomatic

Обычно бывает удобно вызывать метод BeginDrag в обработчике события OnMouseDown перетаскиваемого объекта. Вы уже знакомы с основными параметрами данного события, поэтому нет необходимости рассматривать их подробно.

Отметим, что при использовании данного метода пользователь сам должен позаботиться о проверке корректности начала операции перетаскивания. А именно, перетаскивание должно начинаться только при нажатии левой кнопки мыши (значение Button должно быть равно mbLeft). Следует также отфильтровать двойные щелчки, поскольку их использование при перетаскивании приводит к странным побочным эффектам (значение Shift не должно содержать значения ssDouble, что показывает, что не было двойного щелчка).

Примечание

Для того чтобы начать процесс перетаскивания можно просто в ходе программы в нужном вам месте сделать значение свойства DragMode перетаскиваемого объекта равным dmAutomatic.

При решении упражнения 1 значение свойства DragMode компонетов типа Tshape было установлено в dmAutomatic. Измените его, присовив значение dmManual.

Сохраните проект. Запустите и убедитесь, что процесс Drag&Drop перестал выполняться, так как приложение просто не знает, как ему начать перетаскивание.

Создайте обработчик события OnMouseDown для BWSShp, в котором при нажатии левой кнопкой мыши на выбранном компоненте будет начинаться процесс перетаскивания.

procedure TDrag_Dropfrm.BigSquareWShpMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

If (Button=mbleft) and {нажата левая кнопка мыши}

not(ssDouble in Shift) then {это не двойной щелчок мышью}

(Sender as TShape).begindrag(false);

end;

Сохраните проект. Запустите и убедитесь в том, что после смещения курсора мыши на несколько пикселей при нажатой левой кнопки мыши выполняется процесс Drag&Drop.

Задание

  1. «Ханойские башни». Имеются три колышка A, B, C и n дисков разного размера. Сначала все диски надеты на колышек A так, как показано на рис. ниже. Цель игрока – перенести все диски с колышка A на колышек C, соблюдая при этом следующие условия: диски можно переносить только по одному, больший диск нельзя ставить на меньший. Написать приложение, реализующее эту игру. Приложение должно подсчитывать количество перемещений, а также число минимально возможных перемещений, и показывать эти значения по окончании игры.

При первоначальном запуске выпадает 5 колец, но в параметрах (для создания меню используйте компонент TMainMenu) их количество можно поменять. Для этого необходимо уметь создавать новые компоненты в период работы программы.

Пример создания нового компонента (TShape) во время работы программы:

Var NewS:TShape;

begin

News:=TShape.Create(Form1);

With NewS do

Begin

parent:=Form1;

Name:='Shape2';

Hint:='!';

Width:=100;

Height:=100;

Top:=100;

Left:=100;

DragMode:=dmAutomatic;

brush.color:=clred;

End;

end;

Кроме того, в параметрах можно изменить цвет любого кольца.

В пункте меню «?» выдается справка о программе (условия игры) и информация об авторах.