- •Windows -приложение
- •Среда программирования
- •Встроенный отладчик
- •Использование графики
- •Графические данные и палитра
- •Сохранение проекта
- •Структура приложения
- •Структура модуля
- •Простые типы
- •Символьные типы
- •Логические типы
- •Тип перечень
- •Составной оператор
- •Оператор if
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла repeat
- •Пример приложения 6
- •Пример приложения 7
- •Статические массивы
- •Динамические массивы
- •Оператор with
- •Идентичность типов
- •Совместимость типов
- •Преобразование типов
- •Операторы обработки исключительных ситуаций
- •Рекурсия
- •Процедура exit
- •Директивы подпрограммы
- •Класс как объектный тип
- •Наследование
- •Операции is и as
- •Типы ссылки на класс
- •Типизированные файлы
- •Файлы без типа
- •Пример приложения 17
- •Компонент tmainmenii
- •Двунаправленные списки
- •Потоки данных
- •Пример приложения 22
- •Интерфейс drag and drop
- •Пример приложения 24
- •С файлами
- •Пример приложения 26
- •Программные потоки
- •Приоритеты потоков
- •Класс tthread
- •Проблемы синхронизации потоков
Интерфейс drag and drop
Интерфейс Drag and Drop обеспечивает один из механизмов взаимодействия двух элементов управления во время выполнения приложения. При
179
этом могут выполняться различные операции переноса и приема данных или перемещения элемента, например, на форме. Для того чтобы этот механизм заработал, требуется настроить соответствующим образом с помощью обработчиков событий и инспектора объектов некоторые заданные элементы управления. В заданной паре один должен быть источником (Source), другой -приемником (Target).
Пользователь помещает указатель мыши на нужный элемент, нажимает левую кнопку мыши и, не отпуская ее, начинает перемещение курсора ко второму элементу. При достижении этого элемента пользователь отпускает кнопку мыши. В этот момент выполняются предусмотренные разработчиком действия. Среди этих действий могут быть передача текста, значений свойств, шрифта, простое перемещение с места на место и т.д. Таким образом, Drag and Drop - средство связывания двух компонентов при помощи указателя мыши.
Любой элемент управления является изначально источником в механизме Drag and Drop. Его поведение на начальном этапе настраивается с помощью свойства Property DragMode: TDragMode, где Type TDragMode = (dmManual, dmAutomatic);.
Значение dmAutomatic обеспечивает автоматическую реакцию компонента на нажатие левой кнопки мыши - механизм перетаскивания включается самостоятельно. Значение dmManual (установлено по умолчанию) требует от разработчика обеспечить включение специфических действий при перетаскивании.
Для инициализации переноса в источнике используется метод Begxn-Drag (если не включено dmAutomatic), который можно включить, например, в обработчике OnMouseDown. Приемником может стать любой компонент, для которого создан обработчик события onDragOver. Этот обработчик вызывается при достижении курсором мыши компонента-приемника. Окончание переноса фиксируется работой обработчика OnDragDrop, в котором можно выполнить некоторые действия в приемнике. Определенные действия предусмотрены и в источнике с помощью обработчика OnEndDrag, после того как он получит сообщение об окончании операции переноса. Следует отметить, что не любые действия возможно реализовать.
ПРИМЕР ПРИЛОЖЕНИЯ 23
Рассмотрим пример по использованию Drag and Drop. В программе, приведенной ниже, представлены почти все вышеуказанные виды обработчиков событий по реализации данного интерфейса.
unit Prim23;
interface
uses Windows, Messages, SysUtils, Variants, Classes,Graphics,
180
Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons;
type
TForm1 = class(TForm) Edit1: TEdit;
Edit2: TEdit;
Panel1: TPanel; Panel2: TPanel; Button1: TButton; BitBtnl: TBitBtn;
procedure Edit1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Edit2DragOver(Sender, Source: TObject; X, Y:
Integer; State: TDragState; var Accept: Boolean); procedure Edit2DragDrop(Sender, Source:TObject;
X,Y:Integer);
procedure Edit1EndDrag(Sender, Target: TObject;
X, Y: Integer); procedure FonnDragOver(Sender, Source: TObject;
X, Y: Integer;State: TDragState; var Accept: Boolean) procedure FormDragDrop(Sender, Source: TObject;
X, Y: Integer);
procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var'Accept: Boolean); procedure Panel1DragDrop(Sender, Source: TObject;
X, Y: Integers-end;
var Form1: TForm1; implementation
{$R *.dfm)
procedure TForm1.Edit1MouseDown(Sender: TObject;
Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
if Button=mbLeft then TEdit(Sender).BeginDrag(true);
end;
procedure TForm1.Edit2DragOver(Sender,Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
if Source is TEdit then Accept:=true else Accept:=false;
end;
procedure TForm1.Edit2DragDrop(Sender,Source: TObject;
X, Y: Integer); begin
TEdit(Sender).Text:=TEdit(Source).Text;
TEdit(Sender).SetFocus;
TEdit(Sender).SelectAll;
end;
procedure TForm1.Edit1EndDrag(Sender, Target: TObject;
X, Y: Integer); 181
begin
if Assigned(Target) then TEdit(Sender).Text:=
'Текст перенесен в '+TEdit(Target).Name;
end;
procedure TForm1.FormDragOvar(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean); begin
if (Source.ClassName='TPanel') or (Source.ClassName=
'TButton1) then Accept:=true else Accept:=false; , end;
procedure TForm1.FormDragDrop(Sender, Source: TObject;
X, Y: Integer);
begin
TControl(Source).Left:=x;
TControl(Source).Top:=y;
end;
procedure TForm1.Panel1DragOver(Sender,Source:TObject;
X, Y: Integer'; State: TDragState; var Accept: Boolean); begin
if Source is TButton then Accept:=true else Accept:=false; end;
procedure TForm1.Panel1DragDrop(Sender, Source: TObject;
X, Y: Integer); begin
if Source is TButton then begin
TButton(Source).Left:=(Sender as TPanel).Left+x; TButton(Source).Top:=(Sender as TPanel).Top+y;
if Source is TBitBtn then begin
TBitBtn(Source).Width:=147; TBitBtn(Source).Caption:='Ha форму нельзя';
if Application.MessageBox(PChar('Выход'),
PCharfВыбор варианта'),MB_DEFBUTTON1 + MBICONEXCLAMATION + MB_OKCANCEL) = IDOK then close;
end;
end;
end;
end.
В обработчике Panel1DragDrop как и в Panel1DragOver учитывается, что TBitBtn является вариантом TButton. Если рассматривать форму, то все представленные на ней элементы являются наследниками класса TControl, поэтому в обработчике FormDragDrop не конкретизируются разрешенные к перемещению компоненты. При преобразовании типов объектов использовались две конструкции, например, TButton (Source) или Source as Tbutton, что по результату означает одно и то же. Для элементов Edit1, Edit2 и Panel 1 ("приемник") установлено значение DragMbde = dmManual,
182
для остальных элементов DragMode = dmAutomatic. На рис. 51 представлена форма данного примера.
Вариант выполнения переноса Drag and Drop представлен на рис 52.
Рис. 52
Можно выделить изменение "поведения" кнопки BitBtnl. Она потеряла заданную функцию Close. Для выхода из программы (если не пользоваться
183
стандартным способом закрытия окна) предусмотрен специальный диалог, вызываемый при перемещении данной кнопки.
ТЕХНОЛОГИЯ DRAG AND DOCK
Данная технология реализует динамическое перетаскивание мышью и прицепление одного объекта к другому. В данном механизме участвуют два элемента: один - док (docking site) - может принимать объекты, другой -клиент (dockable control) - присоединяемый компонент. Delphi наделяет данной технологией потомков классов TWinControl и TControl. Класс объекта, играющий роль дока, должен быть производным от класса TWinControl, а класс стыкуемого объекта - от Tcontrol (или TWinControl).
Если рассматривать свойства компонентов, то доком может быть любой объект, обладающий свойством DockSite типа Boolean. Объекты-доки должны быть способны выступать по отношению к другим объектам в качестве контейнеров. Что касается стыкуемых элементов, то подходящие для них компоненты должны иметь два свойства DragKind и DragMode. Как и в случае с технологией перетаскивания Drag and Drop возможны два варианта реализации механизма Drag and Dock, задаваемые в свойстве DragMode: dmManual и dniAuromatie, В свойстве DragKind необходимо задать dkDock.
Иногда в данной технологии бывает полезным свойство AutoSize. Когда оба свойства дока DockSite и AutoSize имеют значение true, док (если это не форма) во время выполнения программы не виден до тех пор, пока к нему не будет пристыкован хотя бы один клиент. Таким поведением часто наделяются компоненты TPanel, которые в этом случае имеют нулевое значение для одного из измерений (высоты или ширины).
Программист для управления данной технологией может воспользоваться рядом обработчиков событий. Реакцию клиента на события, возникающие в моменты начала и конца переноса, можно задавать в обработчиках Оп-StartDock и OnEndDock. Во время переноса можно управлять процессом с помощью следующего ряда подключаемых к доку обработчиков: OnGet-Sitelnfo, OnDockOver, OnDockDrop, OnUnDock. Событие OnGetSitelnfo используется для некоторых компонентов, например для TPanel. Данное событие в самом начале процесса перетаскивания рассылает сообщения и параметры клиента всем потенциальным докам (у которых свойство Dock-Site установлено в true) В ответ док должен сообщить решение о приеме клиента и предоставить прямоугольник приема в случае положительного варианта. Два события OnDockOver и OnDockDrop в точности соответствуют своим аналогам из технологии Drag and Drop. В обработчике OnUnDock можно запрограммировать некоторые действия в момент покидания дока и "приземления" клиента в другом месте.
184
Следует отметить, что реализация технологии Drag and Dock намного сложнее, чем реализация Drag and Drop. В частности, перед стыковкой необходимо вычислять возможный прямоугольник приема. В модуле uDockForm приводится такая функция (ComputeDockingRect). Кроме того, в некоторых сложных вариантах при установке у дока свойства UseDockManager в true возможно использование менеджера контроля докинга (свойство Dock Manager), с помощью которого определяется прямоугольник BoundsRect как быстрый способ получения контроля клиента на доке. Данный менеджер реализует интерфейс IDockManager, имеющий множество возможностей настройки поведения дока. Пристыкованный элемент может быть перемещен в другую позицию при помощи методов ManualDock, ManualFloat, Dock или можно воспользоваться (для некоторых типов клиентов) свойством FloatingDockSiteCIass, устанавливая его значение в CustomDockForm.