Drag & Drop в Delphi или “перетащи и брось”
Drag & Drop в Delphi или «перетащи и брось»
Drag & Drop в Delphi или "перетащи и брось" Drag & Drop - это процесс перетаскивания информации из одного объекта в другой с помощью мыши. Вы можете перемещать все что угодно: файлы, папки, ярлычки, строки между компонентами ListBox или Memo и т.д. Все свойства, события и методы, необходимые нам для осуществления процесса перетаскивания информации между объектами, определены в классе TControl, поэтому для всех визуальных компонент из палитры Delphi они являются общими! Начнем создавать приложение, в котором будем перемещать информацию между ListBox? ами. Для начала нам надо определить, как будет начинаться процесс перетаскивания объекта (строки в нашем случае). За это отвечает свойство DragMode, которое может быть равно: * dmManual - начало процесса перетаскивания должен определить сам программист. Для этого необходимо вызвать метод BeginDrag. Это можно сделать в обработчике события OnMouseDown, где можно проверить, например, нажатие тех или иных клавиш. * dmAutomatic - автоматическое начало перетаскивания объекта при нажатии кнопки мыши над компонентом. При этом событие OnMouseDown, для этого компонента вообще не наступает! Давайте мы сперва разберемся с автоматическим началом процесса перетаскивания, а потом я покажу как использовать ручной старт процесса. Поскольку обработчики других событий, которые нам понадобятся будут одинаковыми для всех компонент, то сделаем так: поставьте на форму два или больше компонента ListBox, заполните их любыми строками (свойство Items), и объедините в группу (удерживая Shift щелкните по каждому из них). В процессе перетаскивания компоненты, над которыми перемещается курсор, могут информировать о том, готовы ли они принять перетаскиваемый объект. Для этого нам понадобится обработать событие OnDragOver, возникающее при перемещении курсора с перетаскиваемым объектом над компонентом. В обработчике этого события предусмотрен параметр Accept, который указывает способен ли компонент принять перетаскиваемый объект. По умолчания оно равно true. Итак, поскольку все списки (ListBox) выделены у нас в одну группу, то перейдем на вкладку Events Инспектора объектов и щелкнем два раза напротив события OnDragOver. Теперь можно писать единый для всех списков обработчик этого события: procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if (Source <> Sender) then Accept:=Source is TListBox else Accept:=false; end; Здесь мы сравниваем является ли перетаскиваемых объект и его источник одним и тем же объектом, и если это не так, то дальше нам надо проверить является ли источник компонентом класса TListBox. Если это истина, то мы разрешаем прием информации. Теперь нам необходимо написать обработчик события OnDragDrop, который определяет процедуру приема информации. Он также будет одинаковым для всех компонент и написан соответственно в общем виде (чтобы его можно было применить в нашей программе сразу ко всем компонентам). Нам надо добавить в список перетаскиваемую строку. Поэтому код получился примерно такой: procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer); begin (Sender as TListBox).Items.Add((Source as TListBox).Items[(Source as TListBox).ItemIndex]); end; Здесь с помощью метода (Sender as TListBox).Items.Add в список Sender добавляется строка. Мы воспользовались операцией as, чтобы указать на класс TListBox, который в отличии от класса TComponent, обладает свойством Items. Не забудьте, что свойство dragMode, у всех списков должно быть равно dmAutomatic. Вот и готов простой пример обмена строк между несколькими списками ListBox. Теперь мы посмотрим, как нам в ручную запустить процесс перетаскивания. Установите для одного из списков свойство dragMode в dmManual, а теперь в обработчике события OnMouseDown, напишите следующее: procedure TForm1.ListBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (ssAlt in Shift) then ListBox1.BeginDrag(false); end; Здесь мы начинаем перетаскивать объект если нажата левая кнопка мыши и удерживается клавша Alt. В этом примере в BeginDrag передано значение false, это говорит о том, что процесс перетаскивания начнется только после движения курсора мыши. Если передать true - то перетаскивание начнется немедленно. С таким же успехом можно организовать перетаскивание изображения и прием его, скажем, на панели. Вот обработчики событий OnDragDrop и OnDragOver для панели (TPanel) и картинки (TImage): procedure TForm1.Panel1DragDrop(Sender, Source: TObject; X, Y: Integer); begin WITH Source AS TImage DO BEGIN Left := X; Top := Y; Parent:=Panel1; // или Form1 если надо принять на форме с именем Form1 END; end; procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := Source IS TImage; end; При этом надо в Image загрузить какое-нибудь изображение, задать свойство dragMode равным dmAutomatic. Ну вот, надеюсь, что и с этим мы разобрались!