17.8. ИНТЕРФЕЙС DRAG&DROP

Операционная система Windows широко использует специальный прием связывания программ с данными, который называется Drag&Drop (перетащи и отпусти). Такой прием в Проводнике windows используется для копирования или перемещения файлов, а также для запуска обрабатывающей программы. Если, например, файл с расширением doc “перетащить” на пиктограмму WinWord, автоматически запустится текстовый редактор word for windows и в его окне появится текст из этого файла.

В Delphi реализован собственный интерфейс Drag&Drop, позволяющий компонентам обмениваться данными путем “перетаскивания” их мышью. Этот интерфейс определяется двумя свойствами и тремя событиями, доступными каждому видимому компоненту.[ В Delphi б события могут дублировать сложные свойства и наоборот. Сложными в данном случае называются свойства, ссылающиеся на внутренние объекты. ]

Свойство

TDragMode = (dmManual, dmAutomatic);

property DragMode: TDragMode;

определяет, как будет выполняться весь комплекс действий, связанных С Drag&Drop: dmManual - Вручную (программой); dmAutomatic -автоматически (свойствами и методами компонентов). Значение dmManual означает, что все необходимые для обслуживания интерфейса события генерируются программой, dmAutomatic - события инициируются свойствами и методами компонентов. Во всех случаях программист должен написать обработчики этих событий (см. ниже).

Свойство property DragCursor: TCursor;

определяет вид указателя мыши в момент, когда над компонентом “протаскиваются данные”. Если компонент готов принять данные, он устанавливает в это свойство значение crDrag l3, в противном случае - crNoDrag 0. Установка этих свойств осуществляется автоматически, если DragMode = dmAutomatic. Событие TDragState = (dsDragEnter, dsDragLeave, dsDragMove) ;

TDragOverEvent = procedure(Sender, Source: TObject;

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

of object; property OnDragOver: TDragOverEvent;

возникает в момент перемещения указателя мыши “с грузом” над компонентом. Здесь sender - компонент, который возбудил событие (обычно это Self - сам компонент-получатель; при ручном управлении механизмом Drag&Drop это может быть не так); source - компонент-отправитель “груза”; х, y - текущие координаты указателя мыши в пикселях клиентской области компонента; State - состояние указателя (dsDragEnter - только что появился на компонентом; dsDragLeave -только что покинул компонент или бьша отпущена кнопка мыши;

dsDragMove - перемещается над компонентом). В параметре Accept обработчик сообщает, готов ли компонент принять данные (т rue - готов).

Событие

TDragDropEvent = procedure(Sender, Source: TObject;

X, Y: Integer) of object;

property OnDragDrop: TDragDropEvent;

означает, что пользователь “бросил” данные на компонент. Параметры обработчика совпадают по назначению с одноименными параметрами OnDragOver.

Наконец, при завершении перетаскивания (вне зависимости от того, приняты данные или нет) возникает событие TEndDragEveht = procedure(Sender, Target: TObject;X, Y: Integer) of objects; property OnEndDrag: TEndDragEvent;

где sender - отправитель данных; Target - получатель данных или nil, если никто не принял “посылку”; X, Y - координаты мыши в момент отпускания левой кнопки.

Чтобы проиллюстрировать использование механизма Drag&Drop, загрузите описанную в гл. 5 учебную программу, установите во всех ее компонентах в свойство DragMode значение dmAutomatic и создайте такой обработчик события OnDragOver для метки:

procedure TfmExample.IbOutputDragOver(Sender, Source: TObject;

X, Y: Integer; State: TDragState;

var Accept: Boolean);

begin

Accept := True;

lbOutput.Caption := (Source as TComponent).Name

end;

Теперь перетаскивание любого компонента на метку IbOutput заставит ее показать имя перетаскиваемого компонента (рис. 17.5).

Рис. 17.5. Метка IbOutput показывает имя перетаскиваемого компонента

Для ручного (программного) управления механизмом Drag&Drop используются следующие методы, доступные любому потомку TControl:

procedure BeginDrag (Immediate: Boolean); | Используется источником для инициализации процесса Drag&Drop. Если Immediate =True, процесс начинается немедленно, в противном случае - после смещения указателя мыши на 5 пикселей в любом направлении
procedure DragDrop (Source: TObject; X, Y: Integer); | Вызывает обработчик события OnDragDrop
procedure EndDrag(Drop: Boolean); | Вызывает обработчик события OnEndDrag и в параметре Drop сообщает о том, были ли приняты данные