Создадим два перекрывающихся графических объекта:
usesABCObjects,GraphABC;
var
r: RectangleABC;
c: CircleABC;
begin
r := newRectangleABC(70,50,200,100,clMoneyGreen);
c := newCircleABC(120,80,110,clBlue);
end.
После запуска программы увидим на экране следующее:
Поменяем некоторые свойства графических объектов и вызовем метод MoveOn для окружности, дописав в конец программы следующие строки:
r.Width := 150;
c.Color := clRed;
c.MoveOn(30,30);
После запуска программы:
Добавим в конец программы следующие строки:
c.Number := 8;
r.Text := 'Hello';
r.ToFront;
После запуска программы:
ABCObjects: контейнеры графических объектов
Класс ContainerABC представляет собой контейнер графических объектов. Он также является потомком ObjectABC, но при создании не содержит ни одного объекта. Он добавляет следующий интерфейс:
procedureAdd(g: ObjectABC);
propertyCount: integer; // количество объектов
propertyObjects[i: integer]: ObjectABC; // i-тый объект
При масштабировании ContainerABC производится масштабирование всех входящих в него объектов. При добавлении объекта в ContainerABC его свойство Owner становится равным этому ContainerABC. При присваивании свойству Owner объекта его владелец меняется, при этом объект перерисовывается как принадлежащий новому владельцу. При присваивании свойству Owner объекта значения nilон перестает иметь владельца и отображается непосредственно в графическом окне.
Рассмотрим следующую программу:
usesABCObjects,GraphABC;
var
c1,c2: ContainerABC;
r: CircleABC;
begin
SetWindowSize(300,300);
c1 := newContainerABC(50,30);
c1.Add( newRectangleABC(0,0,200,100,clGreen));
r := newCircleABC(15,15,70,clYellow);
end.
После ее запуска графический экран имеет вид:

Контейнер c1 содержит зеленый прямоугольник, а объект r не имеет владельца (r.Owner=nil). Нетрудно убедиться, что ObjectsCount=2 (контейнер и круг), а c1.Count=1.
Добавим круг в контейнер, дописав в конец программы строчку
c1.Add(r);
После запуска программы графический экран примет вид:

Круг r теперь принадлежит контейнеру (r.Owner=с2), ObjectsCount=1 (только контейнер), а c1.Count=2. Кроме этого, координаты круга пересчитываются относительно координат контейнера-владельца (они по-прежнему равны (15,15), но относительно левого верхнего угла контейнера c1).
Такой же эффект можно было получить от оператора
r.Owner := c1;
Создадим второй контейнер c2 и поменяем владельца у r на c2. Для этого допишем в конец строки:
c2 := newContainerABC(50,160);
c2.Add( newRectangleABC(0,0,200,100,clMoneyGreen));
r.Owner := c2;
После запуска программы графический экран примет вид:

Как мы видим, круг r поменял владельца, и теперь имеет координаты (15,15), но относительно левого верхнего угла нового владельца c2.
Если вместо строчки r.Owner:=c2; написать r.Owner:= nil; , то круг r потеряет владельца и снова будет позиционироваться относительно левого верхнего угла экрана:

Примеры
Данная программа иллюстрирует применение процедур LockDrawing и Redraw для реализации анимации без мерцания:
usesGraphABC;
begin
LockDrawing;
for vari:=1 to 500 do
begin
Window.Clear;
Brush.Color := clGreen;
Ellipse(i,100,i+100,200);
Redraw;
Sleep(1);
end;
end.
Основная идея состоит в следующем: отключим рисование на экране, вызвав LockDrawing (рисование будет осуществляться только во внеэкранном буфере), после чего будем всякий раз формировать новый кадр изображения и выводить его целиком на экран, вызывая Redraw. При вызове Redraw перерисовывается все графическое окно, поэтому скорость анимации ограничена скоростью вывода внеэкранного буфера на экран.
Читать дальше